commit 638e0b30f6070d3299ca79d97dee13b034e62c09 Author: zerofrog Date: Mon Apr 2 01:06:17 2007 +0000 pcsx2 0.9.3 and a lot of other additions git-svn-id: http://pcsx2.googlecode.com/svn/branches/pcsx2_0.9.1@159 96395faa-99c1-11dd-bbfe-3dabce05a288 diff --git a/CDVD.c b/CDVD.c new file mode 100644 index 0000000000..ab47202d97 --- /dev/null +++ b/CDVD.c @@ -0,0 +1,1806 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PsxCommon.h" +#include "CDVDiso.h" + +cdvdStruct cdvd; + +char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"}; + +char *nCmdName[0x100]= { + "CdSync", "CdNop", "CdStandby", "CdStop", + "CdPause", "CdSeek", "CdRead", "CdReadAudio", + "DvdRead", "CdGetToc", "", "", + "CdReadKey", "", "", "", +}; + +char *sCmdName[0x100]= { + "", "sceCdGetDiscType", "sceCdReadSubQ", "subcommands",//sceCdGetMecaconVersion, read/write console id, read renewal date + "", "sceCdTrayState", "sceCdTrayCtrl", "", + "sceCdReadClock", "sceCdWriteClock", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdSetHDMode", "", "", "sceCdPowerOff", + "", "", "sceCdReadILinkID", "sceCdWriteILinkID", /*10*/ + "sceAudioDigitalOut", "sceForbidDVD", "sceAutoAdjustCtrl", "sceCdReadModelNumber", + "sceWriteModelNumber", "sceCdForbidCD", "sceCdBootCertify", "sceCdCancelPOffRdy", + "sceCdBlueLEDCtl", "", "sceRemote2Read", "sceRemote2_7", + "sceRemote2_6", "sceCdWriteWakeUpTime", "sceCdReadWakeUpTime", "", /*20*/ + "sceCdRcBypassCtl", "", "", "", + "sceCdNoticeGameStart", "sceCdXBSPowerCtl", "sceCdXLEDCtl", "sceCdBuzzerCtl", + "", "", "", "", + "", "sceCdSetMediumRemoval", "sceCdGetMediumRemoval", "sceCdXDVRPReset", /*30*/ + "", "", "__sceCdGetOSDVER", "", + "", "", "", "", + "", "", "", "", + "sceCdOpenConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdCloseConfig", /*40*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*50*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*60*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*70*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "mechacon_auth_0x80", "mechacon_auth_0x81", "mechacon_auth_0x82", "mechacon_auth_0x83", /*80*/ + "", "", "", "", + "", "", "", "", + "sceMgWriteData", "sceMgReadData", "", "mechacon_auth_0x8F", + "sceMgWriteHeaderStart", "sceMgReadBITLength", "sceMgWriteDatainLength", "sceMgWriteDataoutLength", /*90*/ + "sceMgReadKbit", "sceMgReadKbit2", "sceMgReadKcon", "sceMgReadKcon2", + "sceMgReadIcvPs2", "", "", "", + "", "", "", "", + /*A0, no sCmds above?*/ +}; + +// NVM (eeprom) layout info +typedef struct { + u32 biosVer; // bios version that this eeprom layout is for + s32 config1; // offset of 1st config block + s32 config2; // offset of 2nd config block + s32 consoleId; // offset of console id (?) + s32 ilinkId; // offset of ilink id (ilink mac address) + s32 modelNum; // offset of ps2 model number (eg "SCPH-70002") + s32 osdver; // offset of OSDVER for PStwo +} NVMLayout; + +#define NVM_FORMAT_MAX 2 +NVMLayout nvmlayouts[NVM_FORMAT_MAX] = +{ + {0x000, 0x280, 0x300, 0x1C8, 0x1C0, 0x1A0, 0x180}, // eeproms from bios v0.00 and up + {0x160, 0x270, 0x2B0, 0x1C8, 0x1E0, 0x1B0, 0x180}, // eeproms from bios v1.60 and up +}; + + +unsigned long cdvdReadTime=0; + +#define CDVDREAD_INT(eCycle) PSX_INT(19, eCycle) + +#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 SetResultSize(size) \ + cdvd.ResultC = size; cdvd.ResultP = 0; \ + cdvd.sDataIn&=~0x40; + + +/* is cdvd.Status only for NCMDS? (linuzappz) */ +enum cdvdStatus { + CDVD_STATUS_NONE = 0x00, // not sure ;) + CDVD_STATUS_SEEK_COMPLETE = 0x0A, +}; + +static int mg_BIToffset(u8 *buffer); + +FILE *_cdvdOpenMechaVer() { + char *ptr; + int i; + char file[256]; + char Bios[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the mecha ver file + sprintf(file, "%s", Bios); + ptr = file; i = strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "MEC"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenMechaVer: Error creating %s", file); + exit(1); + } + fputc(0x03, fd); + fputc(0x06, fd); + fputc(0x02, fd); + fputc(0x00, fd); + } + return fd; +} +s32 cdvdGetMechaVer(u8* ver) +{ + FILE* fd = _cdvdOpenMechaVer(); + if (fd == NULL) return 1; + fseek(fd, 0, SEEK_SET); + fread(ver, 1, 4, fd); + fclose(fd); + return 0; +} + +FILE *_cdvdOpenNVM() { + char *ptr; + int i; + char Bios[256]; + char file[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the nvm file + sprintf(file, "%s", Bios); + ptr = file; i = strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "NVM"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenNVM: Error creating %s", file); + exit(1); + } + for (i=0; i<1024; i++) fputc(0, fd); + } + return fd; +} + +// +// the following 'cdvd' functions all return 0 if successful +// + +s32 cdvdReadNVM(u8 *dst, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fread(dst, 1, bytes, fd); + fclose(fd); + return 0; +} +s32 cdvdWriteNVM(const u8 *src, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fwrite(src, 1, bytes, fd); + fclose(fd); + return 0; +} + +#define GET_NVM_DATA(buff, offset, size, fmtOffset) getNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) +#define SET_NVM_DATA(buff, offset, size, fmtOffset) setNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) + +s32 getNvmData(u8* buffer, s32 offset, s32 size, u32 biosVersion, s32 fmtOffset) +{ + // find the correct bios version + NVMLayout* nvmLayout = NULL; + s32 nvmIdx; + for(nvmIdx=0; nvmIdx= cdvd.CNumBlocks) + return 1; + else if(cdvd.CBlockIndex >= 4) + { + memcpy(config, 0, 16); + return 0; + } + + // get config data + if(cdvd.COffset == 0) + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); + else + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); +} +s32 cdvdWriteConfig(const u8* config) +{ + // make sure its in write mode + if(cdvd.CReadWrite != 1) + return 1; + // check if block index is in bounds + else if(cdvd.CBlockIndex >= cdvd.CNumBlocks) + return 1; + else if(cdvd.CBlockIndex >= 4) + return 0; + + // get config data + if(cdvd.COffset == 0) + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); + else + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); +} + + +void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { + char str[256]; + int numbers; + int letters; + unsigned int key_0_3; + unsigned char key_4; + unsigned char key_14; + char exeName[12]; + + // get main elf name + GetPS2ElfName(str); + sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]); + SysPrintf("exeName = %s\n",exeName); + + // convert the number characters to a real 32bit number + numbers = ((((exeName[5] - '0'))*10000) + + (((exeName[ 6] - '0'))*1000) + + (((exeName[ 7] - '0'))*100) + + (((exeName[ 9] - '0'))*10) + + (((exeName[10] - '0'))*1) ); + + // combine the lower 7 bits of each char + // to make the 4 letters fit into a single u32 + letters = (int)((exeName[3]&0x7F)<< 0) | + (int)((exeName[2]&0x7F)<< 7) | + (int)((exeName[1]&0x7F)<<14) | + (int)((exeName[0]&0x7F)<<21); + + // calculate magic numbers + key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80 + key_4 = ((numbers & 0x0001F) << 3) | ((0x0E000000 & letters) >> 25); // numbers = F8 letters = 07 + key_14 = ((numbers & 0x003E0) >> 2) | 0x04; // numbers = F8 extra = 04 unused = 03 + + // clear key values + memset(key, 0, 16); + + // store key values + key[ 0] = (key_0_3&0x000000FF)>> 0; + key[ 1] = (key_0_3&0x0000FF00)>> 8; + key[ 2] = (key_0_3&0x00FF0000)>>16; + key[ 3] = (key_0_3&0xFF000000)>>24; + key[ 4] = key_4; + + if(arg2 == 75) + { + key[14] = key_14; + key[15] = 0x05; + } + else if(arg2 == 3075) + { + key[15] = 0x01; + } + else if(arg2 == 4246) + { + // 0x0001F2F707 = sector 0x0001F2F7 dec 0x07 + key[ 0] = 0x07; + key[ 1] = 0xF7; + key[ 2] = 0xF2; + key[ 3] = 0x01; + key[ 4] = 0x00; + key[15] = 0x01; + } + else + { + key[15] = 0x01; + } + + SysPrintf("CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X\n",cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15]); +} + +s32 cdvdGetToc(void* toc) { + s32 ret = CDVDgetTOC(toc); + if(ret == -1) ret = 0x80; + return ret; +/* + cdvdTN diskInfo; + cdvdTD trackInfo; + u8 _time[3]; + u32 type; + int i, err; + + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + type = CDVDgetDiskType(); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + if (type == CDVD_TYPE_CDDA) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x01; + } else + if (type == CDVD_TYPE_PS2DVD) { + if (trackInfo.lsn >= (2048*1024)) { // dual sided + PSXMu8(HW_DMA3_MADR+ 0) = 0x24; + } else { + PSXMu8(HW_DMA3_MADR+ 0) = 0x04; + } + } else + if (type == CDVD_TYPE_PS2CD) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x41; + } + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x04) { + PSXMu8(HW_DMA3_MADR+ 1) = 0x02; + PSXMu8(HW_DMA3_MADR+ 2) = 0xF2; + PSXMu8(HW_DMA3_MADR+ 3) = 0x00; + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x20) { + PSXMu8(HW_DMA3_MADR+ 4) = 0x41; + PSXMu8(HW_DMA3_MADR+ 5) = 0x95; + } else { + PSXMu8(HW_DMA3_MADR+ 4) = 0x86; + PSXMu8(HW_DMA3_MADR+ 5) = 0x72; + } + PSXMu8(HW_DMA3_MADR+ 6) = 0x00; + PSXMu8(HW_DMA3_MADR+ 7) = 0x00; + PSXMu8(HW_DMA3_MADR+ 8) = 0x00; + PSXMu8(HW_DMA3_MADR+ 9) = 0x00; + PSXMu8(HW_DMA3_MADR+10) = 0x00; + PSXMu8(HW_DMA3_MADR+11) = 0x00; + + PSXMu8(HW_DMA3_MADR+12) = 0x00; + PSXMu8(HW_DMA3_MADR+13) = 0x00; + PSXMu8(HW_DMA3_MADR+14) = 0x00; + PSXMu8(HW_DMA3_MADR+15) = 0x00; + + PSXMu8(HW_DMA3_MADR+16) = 0x00; + PSXMu8(HW_DMA3_MADR+17) = 0x03; + PSXMu8(HW_DMA3_MADR+18) = 0x00; + PSXMu8(HW_DMA3_MADR+19) = 0x00; + + } else { + PSXMu8(HW_DMA3_MADR+ 1) = 0x00; + PSXMu8(HW_DMA3_MADR+ 2) = 0xA0; + PSXMu8(HW_DMA3_MADR+ 7) = itob(diskInfo.strack);//Number of FirstTrack + + PSXMu8(HW_DMA3_MADR+12) = 0xA1; + PSXMu8(HW_DMA3_MADR+17) = itob(diskInfo.etrack);//Number of LastTrack + + PSXMu8(HW_DMA3_MADR+22) = 0xA2;//DiskLength + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+27) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+28) = itob(_time[1]); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) { + err=CDVDgetTD(i, &trackInfo); + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+i*10+30) = trackInfo.type; + PSXMu8(HW_DMA3_MADR+i*10+32) = err == -1 ? 0 : itob(i); //number + PSXMu8(HW_DMA3_MADR+i*10+37) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+i*10+38) = itob(_time[1]); + PSXMu8(HW_DMA3_MADR+i*10+39) = itob(_time[0]); + } + } +*/ +} + +s32 cdvdReadSubQ(s32 lsn, cdvdSubQ* subq) +{ + s32 ret = CDVDreadSubQ(lsn, subq); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayOpen() +{ + s32 ret = CDVDctrlTrayOpen(); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayClose() +{ + s32 ret = CDVDctrlTrayClose(); + if(ret == -1) ret = 0x80; + return ret; +} + +// Modified by (efp) - 16/01/2006 +// checks if tray was opened since last call to this func +s32 cdvdGetTrayStatus() +{ + s32 ret = CDVDgetTrayStatus(); + // get current tray state + if (cdCaseopen) return(CDVD_TRAY_OPEN); + + + if (ret == -1) return(CDVD_TRAY_CLOSE); + return(ret); +} +// Note: Is tray status being kept as a var here somewhere? +// cdvdNewDiskCB() can update it's status as well... + +// Modified by (efp) - 16/01/2006 +s32 cdvdGetDiskType() { + // defs 0.9.0 + if(CDVDnewDiskCB) return(cdvd.Type); + + // defs.0.8.1 + if(cdvdGetTrayStatus() == CDVD_TRAY_OPEN) return(CDVD_TYPE_NODISC); + // Note: Hmmm. Need to modify cdvd.Type as well? + // or just throw it out. CDVDgetDiskType() sets type to "NODISC" anyway. + + cdvd.Type = CDVDgetDiskType(); + if (cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if (GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? + return(cdvd.Type); +} // END cdvdGetDiskType() + + +// check whether disc is single or dual layer +// if its dual layer, check what the disctype is and what sector number +// layer1 starts at +// +// args: gets value for dvd type (0=single layer, 1=ptp, 2=otp) +// gets value for start lsn of layer1 +// returns: 1 if on dual layer disc +// 0 if not on dual layer disc +s32 cdvdReadDvdDualInfo(s32* dualType, u32* layer1Start) +{ + u8 toc[2064]; + *dualType = 0; + *layer1Start = 0; + + // if error getting toc, settle for single layer disc ;) + if(cdvdGetToc(toc)) + return 0; + if(toc[14] & 0x60) + { + if(toc[14] & 0x10) + { + // otp dvd + *dualType = 2; + *layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1; + } + else + { + // ptp dvd + *dualType = 1; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + } + else + { + // single layer dvd + *dualType = 0; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + + return 1; +} + + +void cdvdReset() { + memset(&cdvd, 0, sizeof(cdvd)); + cdvd.sDataIn = 0x40; + cdvd.Ready = 0x4e; + cdCaseopen = 0; + cdvd.Speed = 4; + cdvd.BlockSize = 2064; + cdvdReadTimeRcnt(0); +} +void cdvdReadTimeRcnt(int mode){ // Mode 0 is DVD, Mode 1 is CD + int readsize = 0; // 1 Sector size + int amount = 0; // Total bytes transfered at 1x speed + //if(mode) amount = 153600; + //else + amount = 1280000; + + readsize = amount / cdvd.BlockSize; // Time taken for 1 sector to be read + cdvdReadTime = ((PSXCLK / readsize) / BIAS) / cdvd.Speed; +} + +int cdvdFreeze(gzFile f, int Mode) { + gzfreeze(&cdvd, sizeof(cdvd)); + if (Mode == FREEZE_LOAD) { + if (cdvd.Reading) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + } + } + + return 0; +} + +int cdvdInterrupt() { + return 1; +} + +// Modified by (efp) - 16/01/2006 +void cdvdNewDiskCB() { + cdvd.Type = CDVDgetDiskType(); + if(cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if(GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? +} // END cdvdNewDiskCB() + +void mechaDecryptBytes(unsigned char* buffer, int size) +{ + int i; + + int shiftAmount = (cdvd.decSet>>4) & 7; + int doXor = (cdvd.decSet) & 1; + int doShift = (cdvd.decSet) & 2; + unsigned char key = cdvd.Key[4]; + + for(i=0; i>shiftAmount) | (buffer[i]<<(8-shiftAmount)); + } +} + +int cdvdReadSector() { + s32 bcr; + +#ifdef CDR_LOG + CDR_LOG("SECTOR %d (BCR %x;%x)\n", cdvd.Sector, HW_DMA3_BCR_H16, HW_DMA3_BCR_L16); +#endif + bcr = (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4; + if (bcr < cdvd.BlockSize) { + //SysPrintf("*PCSX2*: cdvdReadSector: bcr < cdvd.BlockSize; %x < %x\n", bcr, cdvd.BlockSize); + if (HW_DMA3_CHCR & 0x01000000) { + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + } + return -1; + } + + // if raw dvd sector 'fill in the blanks' + if (cdvd.BlockSize == 2064) { + // get info on dvd type and layer1 start + u32 layer1Start; + s32 dualType; + s32 layerNum; + u32 lsn = cdvd.Sector; + cdvdReadDvdDualInfo(&dualType, &layer1Start); + + if((dualType == 1) && (lsn >= layer1Start)) { + // dual layer ptp disc + layerNum = 1; + lsn = lsn-layer1Start + 0x30000; + } else if((dualType == 2) && (lsn >= layer1Start)) { + // dual layer otp disc + layerNum = 1; + lsn = ~(layer1Start+0x30000 - 1); + } else { + // single layer disc + // or on first layer of dual layer disc + layerNum = 0; + lsn += 0x30000; + } // ENDLONGIF- Assumed the other dualType is 0. + + PSXMu8(HW_DMA3_MADR+0) = 0x20 | layerNum; + PSXMu8(HW_DMA3_MADR+1) = (u8)(lsn >> 16); + PSXMu8(HW_DMA3_MADR+2) = (u8)(lsn >> 8); + PSXMu8(HW_DMA3_MADR+3) = (u8)(lsn ); + + // sector IED (not calculated at present) + PSXMu8(HW_DMA3_MADR+4) = 0; + PSXMu8(HW_DMA3_MADR+5) = 0; + + // sector CPR_MAI (not calculated at present) + PSXMu8(HW_DMA3_MADR+ 6) = 0; + PSXMu8(HW_DMA3_MADR+ 7) = 0; + PSXMu8(HW_DMA3_MADR+ 8) = 0; + PSXMu8(HW_DMA3_MADR+ 9) = 0; + PSXMu8(HW_DMA3_MADR+10) = 0; + PSXMu8(HW_DMA3_MADR+11) = 0; + + // normal 2048 bytes of sector data + memcpy_amd(PSXM(HW_DMA3_MADR+12), cdr.pTransfer, 2048); + + // 4 bytes of edc (not calculated at present) + PSXMu8(HW_DMA3_MADR+2060) = 0; + PSXMu8(HW_DMA3_MADR+2061) = 0; + PSXMu8(HW_DMA3_MADR+2062) = 0; + PSXMu8(HW_DMA3_MADR+2063) = 0; + } else { + // normal read + memcpy_amd(PSXM(HW_DMA3_MADR), cdr.pTransfer, cdvd.BlockSize); + } + // decrypt sector's bytes + if(cdvd.decSet) + mechaDecryptBytes(PSXM(HW_DMA3_MADR), cdvd.BlockSize); + +// SysPrintf("sector %x;%x;%x\n", PSXMu8(HW_DMA3_MADR+0), PSXMu8(HW_DMA3_MADR+1), PSXMu8(HW_DMA3_MADR+2)); + + HW_DMA3_BCR_H16-= (cdvd.BlockSize / (HW_DMA3_BCR_L16*4)); + HW_DMA3_MADR+= cdvd.BlockSize; + //FreezeMMXRegs(0); + + return 0; +} + +int cdvdReadInterrupt() { + + //SysPrintf("cdvdReadInterrupt %x %x %x %x %x\n", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4); + if (cdvd.Readed == 0) { + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + cdvd.Readed = 1; + cdvd.Status = CDVD_STATUS_SEEK_COMPLETE; + + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + if (cdvd.Reading == 1) { + if (cdvd.RErr == 0) { + cdr.pTransfer = CDVDgetBuffer(); + } else cdr.pTransfer = NULL; + if (cdr.pTransfer == NULL) { + cdvd.RetryCntP++; + SysPrintf("READ ERROR %d\n", cdvd.Sector); + if (cdvd.RetryCntP <= cdvd.RetryCnt) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + } + cdvd.Reading = 0; + } + if (cdvdReadSector() == -1) { + assert( (int)cdvdReadTime > 0 ); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + cdvd.Sector++; + + if (--cdvd.nSectors <= 0) { + psxHu32(0x1070)|= 0x4; + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + return 1; + } + + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdr.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; +} + +void cdvdVsync() { + cdvd.RTCcount++; + if (cdvd.RTCcount < 60) return; + cdvd.RTCcount = 0; + + cdvd.RTC.second++; + if (cdvd.RTC.second < 60) return; + cdvd.RTC.second = 0; + + cdvd.RTC.minute++; + if (cdvd.RTC.minute < 60) return; + cdvd.RTC.minute = 0; + + cdvd.RTC.hour++; + if (cdvd.RTC.hour < 24) return; + cdvd.RTC.hour = 0; + + cdvd.RTC.day++; + if (cdvd.RTC.day < 30) return; + cdvd.RTC.day = 0; + + cdvd.RTC.month++; + if (cdvd.RTC.month < 12) return; + cdvd.RTC.month = 0; + + cdvd.RTC.year++; +} + + +u8 cdvdRead04(void) { // NCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead04(NCMD) %x\n", cdvd.nCommand); +#endif + return cdvd.nCommand; +} + +u8 cdvdRead05(void) { // N-READY +#ifdef CDR_LOG + CDR_LOG("cdvdRead05(NReady) %x\n", cdvd.Ready); +#endif + return cdvd.Ready; +} + +u8 cdvdRead06(void) { // ERROR +#ifdef CDR_LOG + CDR_LOG("cdvdRead06(Error) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead07(void) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdRead07(Break) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead08(void) { // PWOFF +#ifdef CDR_LOG + CDR_LOG("cdvdRead08(PowerOff) %x\n", cdvd.PwOff); +#endif + return cdvd.PwOff; +} + +u8 cdvdRead0A(void) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdRead0A(Status) %x\n", cdvd.Status); +#endif + return cdvd.Status; +} + +u8 cdvdRead0B(void) { // TRAY-STATE (if tray has been opened) + u8 tray = cdvdGetTrayStatus(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0B(Tray) %x\n", tray); +#endif + return tray; +} + +u8 cdvdRead0C(void) { // CRT MINUTE +#ifdef CDR_LOG + CDR_LOG("cdvdRead0C(Min) %x\n", itob((u8)(cdvd.Sector/(60*75)))); +#endif + return itob((u8)(cdvd.Sector/(60*75))); +} + +u8 cdvdRead0D(void) { // CRT SECOND +#ifdef CDR_LOG + CDR_LOG("cdvdRead0D(Sec) %x\n", itob((u8)((cdvd.Sector/75)%60)+2)); +#endif + return itob((u8)((cdvd.Sector/75)%60)+2); +} + +u8 cdvdRead0E(void) { // CRT FRAME +#ifdef CDR_LOG + CDR_LOG("cdvdRead0E(Frame) %x\n", itob((u8)(cdvd.Sector%75))); +#endif + return itob((u8)(cdvd.Sector%75)); +} + +u8 cdvdRead0F(void) { // TYPE + u8 type = cdvdGetDiskType(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0F(Disc Type) %x\n", type); +#endif + return type; +} + +u8 cdvdRead13(void) { // UNKNOWN +#ifdef CDR_LOG + CDR_LOG("cdvdRead13(Unknown) %x\n", 4); +#endif + return 4; +} + +u8 cdvdRead15(void) { // RSV +#ifdef CDR_LOG + CDR_LOG("cdvdRead15(RSV)\n"); +#endif + return 0x01; // | 0x80 for ATAPI mode +} + +u8 cdvdRead16(void) { // SCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead16(SCMD) %x\n", cdvd.sCommand); +#endif + return cdvd.sCommand; +} + +u8 cdvdRead17(void) { // SREADY +#ifdef CDR_LOG + CDR_LOG("cdvdRead17(SReady) %x\n", cdvd.sDataIn); +#endif + return cdvd.sDataIn; +} + +u8 cdvdRead18(void) { // SDATAOUT + u8 ret=0; + + if ((cdvd.sDataIn & 0x40) == 0) { + if (cdvd.ResultP < cdvd.ResultC) { + cdvd.ResultP++; + if (cdvd.ResultP >= cdvd.ResultC) cdvd.sDataIn|= 0x40; + ret = cdvd.Result[cdvd.ResultP-1]; + } + } + +#ifdef CDR_LOG + CDR_LOG("cdvdRead18(SDataOut) %x (ResultC=%d, ResultP=%d)\n", ret, cdvd.ResultC, cdvd.ResultP); +#endif + + return ret; +} + +u8 cdvdRead20(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead20(Key0) %x\n", cdvd.Key[0]); +#endif + return cdvd.Key[0]; +} + +u8 cdvdRead21(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead21(Key1) %x\n", cdvd.Key[1]); +#endif + return cdvd.Key[1]; +} + +u8 cdvdRead22(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead22(Key2) %x\n", cdvd.Key[2]); +#endif + return cdvd.Key[2]; +} + +u8 cdvdRead23(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead23(Key3) %x\n", cdvd.Key[3]); +#endif + return cdvd.Key[3]; +} + +u8 cdvdRead24(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead24(Key4) %x\n", cdvd.Key[4]); +#endif + return cdvd.Key[4]; +} + +u8 cdvdRead28(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead28(Key5) %x\n", cdvd.Key[5]); +#endif + return cdvd.Key[5]; +} + +u8 cdvdRead29(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead29(Key6) %x\n", cdvd.Key[6]); +#endif + return cdvd.Key[6]; +} + +u8 cdvdRead2A(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2A(Key7) %x\n", cdvd.Key[7]); +#endif + return cdvd.Key[7]; +} + +u8 cdvdRead2B(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2B(Key8) %x\n", cdvd.Key[8]); +#endif + return cdvd.Key[8]; +} + +u8 cdvdRead2C(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2C(Key9) %x\n", cdvd.Key[9]); +#endif + return cdvd.Key[9]; +} + +u8 cdvdRead30(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead30(Key10) %x\n", cdvd.Key[10]); +#endif + return cdvd.Key[10]; +} + +u8 cdvdRead31(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead31(Key11) %x\n", cdvd.Key[11]); +#endif + return cdvd.Key[11]; +} + +u8 cdvdRead32(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead32(Key12) %x\n", cdvd.Key[12]); +#endif + return cdvd.Key[12]; +} + +u8 cdvdRead33(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead33(Key13) %x\n", cdvd.Key[13]); +#endif + return cdvd.Key[13]; +} + +u8 cdvdRead34(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead34(Key14) %x\n", cdvd.Key[14]); +#endif + return cdvd.Key[14]; +} + +u8 cdvdRead38(void) { // valid parts of key data (first and last are valid) +#ifdef CDR_LOG + CDR_LOG("cdvdRead38(KeysValid) %x\n", cdvd.Key[15]); +#endif + return cdvd.Key[15]; +} + +u8 cdvdRead39(void) { // KEY-XOR +#ifdef CDR_LOG + CDR_LOG("cdvdRead39(KeyXor) %x\n", cdvd.KeyXor); +#endif + return cdvd.KeyXor; +} + +u8 cdvdRead3A(void) { // DEC_SET +#ifdef CDR_LOG + CDR_LOG("cdvdRead3A(DecSet) %x\n", cdvd.decSet); +#endif + SysPrintf("DecSet Read: %02X\n", cdvd.decSet); + return cdvd.decSet; +} + + + +void cdvdWrite04(u8 rt) { // NCOMMAND + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite04: NCMD %s (%x) (ParamP = %x)\n", nCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.nCommand = rt; + cdvd.Status = CDVD_STATUS_NONE; + switch (rt) { + case 0x00: // CdNop + case 0x01: // CdNop_ + psxHu32(0x1070)|= 0x4; + break; + + // from an emulation point of view there is not much need to do anything for these + case 0x02: // CdStandby + case 0x03: // CdStop + case 0x04: // CdPause + psxHu32(0x1070)|= 0x4; + break; + // should we change the sector location here? + case 0x05: // CdSeek + cdvd.Sector = *(int*)(cdvd.Param+0); + psxHu32(0x1070)|= 0x4; + break; + + case 0x06: // CdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; // CD + case 0x02: cdvd.Speed = 2; break; // CD + case 0x03: cdvd.Speed = 4; break; // CD + case 0x04: cdvd.Speed = 12; break; // CD + default: cdvd.Speed = 24; break; // CD + } + switch (cdvd.Param[10]) { + case 2: cdvd.ReadMode = CDVD_MODE_2340; cdvd.BlockSize = 2340; break; + case 1: cdvd.ReadMode = CDVD_MODE_2328; cdvd.BlockSize = 2328; break; + case 0: default: cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2048; break; + } + if(cdvd.Speed > 4) cdvdReadTimeRcnt(1); + else cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "CdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("CdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + CDVDREAD_INT(1); + + break; + + case 0x07: // CdReadAudio + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; + case 0x02: cdvd.Speed = 2; break; + case 0x03: cdvd.Speed = 4; break; + case 0x04: cdvd.Speed = 12; break; + default: cdvd.Speed = 24; break; + } + switch (cdvd.Param[10]) { + case 1: cdvd.ReadMode = CDVD_MODE_2368; cdvd.BlockSize = 2368; break; + case 2: + case 0: cdvd.ReadMode = CDVD_MODE_2352; cdvd.BlockSize = 2352; break; + } + cdvdReadTimeRcnt(1); + SysPrintf("CdAudioRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + CDVDREAD_INT(1); + break; + + case 0x08: // DvdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + cdvd.Speed = 4; + cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2064; // Why oh why was it 2064 + cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "DvdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("DvdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + cdvd.Readed = 0; + CDVDREAD_INT(1); + break; + + case 0x09: // CdGetToc & cdvdman_call19 + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + cdvdGetToc(PSXM(HW_DMA3_MADR)); + psxHu32(0x1070)|= 0x4; + break; + + case 0x0C: // CdReadKey + { + unsigned char arg0 = cdvd.Param[0]; + unsigned short arg1 = cdvd.Param[1] | (cdvd.Param[2]<<8); + unsigned int arg2 = cdvd.Param[3] | (cdvd.Param[4]<<8) | (cdvd.Param[5]<<16) | (cdvd.Param[6]<<24); + SysPrintf("cdvdReadKey(%d, %d, %d)\n", arg0, arg1, arg2); + cdvdReadKey(arg0, arg1, arg2, cdvd.Key); + cdvd.KeyXor = 0x00; + psxHu32(0x1070)|= 0x4; + break; + } + default: + SysPrintf("NCMD Unknown %x\n", rt); + psxHu32(0x1070)|= 0x4; + break; + } + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite05(u8 rt) { // NDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite05(NDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite06(u8 rt) { // HOWTO +#ifdef CDR_LOG + CDR_LOG("cdvdWrite06(HowTo) %x\n", rt); +#endif + cdvd.HowTo = rt; +} + +void cdvdWrite07(u8 rt) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdWrite07(Break) %x\n", rt); +#endif + SysPrintf("*PCSX2*: CDVD BREAK %x\n" , rt); +} + +void cdvdWrite08(u8 rt) { // PWOFF +#ifdef CDR_LOG + CDR_LOG("cdvdWrite08(PowerOff) %x\n", rt); +#endif +} + +void cdvdWrite0A(u8 rt) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0A(Status) %x\n", rt); +#endif +} + +void cdvdWrite0F(u8 rt) { // TYPE +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0F(Type) %x\n", rt); +#endif +SysPrintf("*PCSX2*: CDVD TYPE %x\n", rt); +} + +void cdvdWrite14(u8 rt) { // PS1 MODE?? + u32 cycle = psxRegs.cycle; + psxReset(); + psxHu32(0x1f801450) = 0x8; + psxHu32(0x1f801078) = 1; + psxRegs.cycle = cycle; + +#ifdef PCSX2_DEVBUILD + varLog|= 0x10000000;// | 0x00400000;// | 0x1fe00000; +#endif +} + +void cdvdWrite16(u8 rt) { // SCOMMAND +// cdvdTN diskInfo; +// cdvdTD trackInfo; +// int i, lbn, type, min, sec, frm, address; + int address; + u8 tmp; + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite16: SCMD %s (%x) (ParamP = %x)\n", sCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.sCommand = rt; + switch (rt) { + +// case 0x01: // GetDiscType - from cdvdman (0:1) +// SetResultSize(1); +// cdvd.Result[0] = 0; +// break; + + case 0x02: // CdReadSubQ (0:11) + SetResultSize(11); + cdvd.Result[0] = cdvdReadSubQ(cdvd.Sector, (cdvdSubQ*)&cdvd.Result[1]); + break; + + case 0x03: // Mecacon-command + if(cdvd.Param[0]==0x00) { + // get mecha version (1:4) + SetResultSize(4); + cdvdGetMechaVer(&cdvd.Result[0]); + } + else if(cdvd.Param[0]==0x44) { + // write console ID (9:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteConsoleID(&cdvd.Param[1]); + } + else if(cdvd.Param[0]==0x45) { + // read console ID (1:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadConsoleID(&cdvd.Result[1]); + } + else if(cdvd.Param[0]==0xFD) { + // _sceCdReadRenewalDate (1:6) BCD + SetResultSize(6); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0x04;//year + cdvd.Result[2] = 0x12;//month + cdvd.Result[3] = 0x10;//day + cdvd.Result[4] = 0x01;//hour + cdvd.Result[5] = 0x30;//min + } else { + SetResultSize(1); + cdvd.Result[0] = 0x80; + SysPrintf("*Unknown Mecacon Command param[0]=%02X\n", cdvd.Param[0]); + } + break; + + case 0x05: // CdTrayReqState (0:1) - resets the tray open detection + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x06: // CdTrayCtrl (1:1) + SetResultSize(1); + if(cdvd.Param[0] == 0) + cdvd.Result[0] = cdvdCtrlTrayOpen(); + else + cdvd.Result[0] = cdvdCtrlTrayClose(); + break; + + case 0x08: // CdReadRTC (0:8) + SetResultSize(8); + memcpy_amd(cdvd.Result, (u8*)&cdvd.RTC, 8); + /* do not uncomment this by now, it kinda makes + things a bit more random for debugging (linuz) */ +/* + { + time_t sysTime; + struct tm* utcTime; + time(&sysTime); + utcTime = gmtime(&sysTime); + cdvd.RTC.second =itob((u8)utcTime->tm_sec); + cdvd.RTC.minute =itob((u8)utcTime->tm_min); + cdvd.RTC.hour =itob((u8)utcTime->tm_hour); // add 8 to the hours (the ps2 wants it this way) + cdvd.RTC.day =itob((u8)utcTime->tm_mday); + cdvd.RTC.month =itob((u8)utcTime->tm_mon); + cdvd.RTC.year =itob((u8)(utcTime->tm_year+100)); + cdvd.RTC.pad =0; + } +*/ + break; + + case 0x09: // sceCdWriteRTC (7:1) + SetResultSize(1); + cdvd.Result[0] = 0; + memcpy_amd((u8*)&cdvd.RTC, cdvd.Param, 7); + cdvd.RTC.pad = 0; + break; + + case 0x0A: // sceCdReadNVM (2:3) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + if (address < 512) { + SetResultSize(3); + cdvd.Result[0] = cdvdReadNVM(&cdvd.Result[1], address*2, 2); + // swap bytes around + tmp = cdvd.Result[1]; + cdvd.Result[1] = cdvd.Result[2]; + cdvd.Result[2] = tmp; + } else { + SetResultSize(1); + cdvd.Result[0] = 0xff; + } + break; + + case 0x0B: // sceCdWriteNVM (4:1) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + SetResultSize(1); + if (address < 512) { + // swap bytes around + tmp = cdvd.Param[2]; + cdvd.Param[2] = cdvd.Param[3]; + cdvd.Param[3] = tmp; + cdvd.Result[0] = cdvdWriteNVM(&cdvd.Param[2], address*2, 2); + } else { + cdvd.Result[0] = 0xff; + } + break; + +// case 0x0C: // sceCdSetHDMode (1:1) +// break; + + + case 0x0F: // sceCdPowerOff (0:1)- Call74 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x12: // sceCdReadILinkId (0:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadILinkID(&cdvd.Result[1]); + break; + + case 0x13: // sceCdWriteILinkID (8:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteILinkID(&cdvd.Param[1]); + break; + + case 0x14: // CdCtrlAudioDigitalOut (1:1) + //parameter can be 2, 0, ... + SetResultSize(1); + cdvd.Result[0] = 0; //8 is a flag; not used + break; + + case 0x15: // sceCdForbidDVDP (0:1) + //SysPrintf("sceCdForbidDVDP\n"); + SetResultSize(1); + cdvd.Result[0] = 5; + break; + + case 0x16: // AutoAdjustCtrl - from cdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x17: // CdReadModelNumber (1:9) - from xcdvdman + SetResultSize(9); + cdvd.Result[0] = cdvdReadModelNumber(&cdvd.Result[1], cdvd.Param[0]); + break; + + case 0x18: // CdWriteModelNumber (9:1) - from xcdvdman + SetResultSize(1); + cdvd.Result[0] = cdvdWriteModelNumber(&cdvd.Param[1], cdvd.Param[0]); + break; + +// case 0x19: // sceCdForbidRead (0:1) - from xcdvdman +// break; + + case 0x1A: // sceCdBootCertify (4:1) + SetResultSize(1);//on imput there are 4 bytes: 1;?10;J;C for 18000; 1;60;E;C for 39002 from ROMVER + cdvd.Result[0]=1;//i guess that means okay + break; + + case 0x1B: // sceCdCancelPOffRdy (0:1) - Call73 from Xcdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x1C: // sceCdBlueLEDCtl (1:1) - Call72 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x1D: // cdvdman_call116 (0:5) - In V10 Bios +// break; + + case 0x1E: // sceRemote2Read (0:5) - // 00 14 AA BB CC -> remote key code + SetResultSize(5); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x14; + cdvd.Result[2] = 0x00; + cdvd.Result[3] = 0x00; + cdvd.Result[4] = 0x00; + break; + +// case 0x1F: // sceRemote2_7 (2:1) - cdvdman_call117 +// break; + + case 0x20: // sceRemote2_6 (0:3) // 00 01 00 + SetResultSize(3); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x01; + cdvd.Result[2] = 0x00; + break; + +// case 0x21: // sceCdWriteWakeUpTime (8:1) +// break; + + case 0x22: // sceCdReadWakeUpTime (0:10) + SetResultSize(10); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0; + cdvd.Result[2] = 0; + cdvd.Result[3] = 0; + cdvd.Result[4] = 0; + cdvd.Result[5] = 0; + cdvd.Result[6] = 0; + cdvd.Result[7] = 0; + cdvd.Result[8] = 0; + cdvd.Result[9] = 0; + break; + + case 0x24: // sceCdRCBypassCtrl (1:1) - In V10 Bios + // FIXME: because PRId<0x23, the bit 0 of sio2 don't get updated 0xBF808284 + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x25: // cdvdman_call120 (1:1) - In V10 Bios +// break; + +// case 0x26: // cdvdman_call128 (0,3) - In V10 Bios +// break; + +// case 0x27: // cdvdman_call148 (0:13) - In V10 Bios +// break; + +// case 0x28: // cdvdman_call150 (1:1) - In V10 Bios +// break; + +// case 0x29: //sceCdNoticeGameStart (1:1) +// break; + +// case 0x2C: //sceCdXBSPowerCtl (2:2) +// break; + +// case 0x2D: //sceCdXLEDCtl (2:2) +// break; + +// case 0x2E: //sceCdBuzzerCtl (0:1) +// break; + +// case 0x2F: //cdvdman_call167 (16:1) +// break; + +// case 0x30: //cdvdman_call169 (1:9) +// break; + + case 0x31: //sceCdSetMediumRemoval (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x32: //sceCdGetMediumRemoval (0:2) + SetResultSize(2); + cdvd.Result[0] = 0; + cdvd.Result[0] = 0; + break; + +// case 0x33: //sceCdXDVRPReset (1:1) +// break; + + case 0x36: //cdvdman_call189 [__sceCdGetOSDVER - made up name] (0:15) + SetResultSize(15); + cdvd.Result[0] = cdvdReadOSDVER(&cdvd.Result[3]); + cdvd.Result[1] = 0;//0x10 + cdvd.Result[2] = 0; + cdvd.Result[11] = 0; + cdvd.Result[12] = 0; + cdvd.Result[13] = 0;//0xFF + cdvd.Result[14] = 0; + SysPrintf("OSDVer = %s\n",&cdvd.Result[3]); + break; + + case 0x3E: //[__sceCdSetOSDVER - made up name] (15:1) [Florin: hum, i was expecting 14:1] + SetResultSize(1); + cdvd.Result[0] = cdvdWriteOSDVER(&cdvd.Param[2]); + break; + + case 0x40: // CdOpenConfig (3:1) + cdvd.CReadWrite = cdvd.Param[0]; + cdvd.COffset = cdvd.Param[1]; + cdvd.CNumBlocks = cdvd.Param[2]; + cdvd.CBlockIndex= 0; + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x41: // CdReadConfig (0:16) + SetResultSize(16); + cdvdReadConfig(&cdvd.Result[0]); + break; + + case 0x42: // CdWriteConfig (16:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteConfig(&cdvd.Param[0]); + break; + + case 0x43: // CdCloseConfig (0:1) + cdvd.CReadWrite = 0; + cdvd.COffset = 0; + cdvd.CNumBlocks = 0; + cdvd.CBlockIndex= 0; + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x80: // secrman: __mechacon_auth_0x80 + cdvd.mg_datatype = 0;//data + SetResultSize(1);//in:1 + cdvd.Result[0] = 0; + break; + + case 0x81: // secrman: __mechacon_auth_0x81 + cdvd.mg_datatype = 0;//data + SetResultSize(1);//in:1 + cdvd.Result[0] = 0; + break; + + case 0x82: // secrman: __mechacon_auth_0x82 + SetResultSize(1);//in:16 + cdvd.Result[0] = 0; + break; + + case 0x83: // secrman: __mechacon_auth_0x83 + SetResultSize(1);//in:8 + cdvd.Result[0] = 0; + break; + + case 0x84: // secrman: __mechacon_auth_0x84 + SetResultSize(1+8+4);//in:0 + cdvd.Result[0] = 0; + + cdvd.Result[1] = 0x21; + cdvd.Result[2] = 0xdc; + cdvd.Result[3] = 0x31; + cdvd.Result[4] = 0x96; + cdvd.Result[5] = 0xce; + cdvd.Result[6] = 0x72; + cdvd.Result[7] = 0xe0; + cdvd.Result[8] = 0xc8; + + cdvd.Result[9] = 0x69; + cdvd.Result[10] = 0xda; + cdvd.Result[11] = 0x34; + cdvd.Result[12] = 0x9b; + break; + + case 0x85: // secrman: __mechacon_auth_0x85 + SetResultSize(1+4+8);//in:0 + cdvd.Result[0] = 0; + + cdvd.Result[1] = 0xeb; + cdvd.Result[2] = 0x01; + cdvd.Result[3] = 0xc7; + cdvd.Result[4] = 0xa9; + + cdvd.Result[ 5] = 0x3f; + cdvd.Result[ 6] = 0x9c; + cdvd.Result[ 7] = 0x5b; + cdvd.Result[ 8] = 0x19; + cdvd.Result[ 9] = 0x31; + cdvd.Result[10] = 0xa0; + cdvd.Result[11] = 0xb3; + cdvd.Result[12] = 0xa3; + break; + + case 0x86: // secrman: __mechacon_auth_0x86 + SetResultSize(1);//in:16 + cdvd.Result[0] = 0; + break; + + case 0x87: // secrman: __mechacon_auth_0x87 + SetResultSize(1);//in:8 + cdvd.Result[0] = 0; + break; + + case 0x8D: // sceMgWriteData + SetResultSize(1);//in:length<=16 + if (cdvd.mg_size + cdvd.ParamC > cdvd.mg_maxsize) + cdvd.Result[0] = 0x80; + else{ + memcpy(cdvd.mg_buffer + cdvd.mg_size, cdvd.Param, cdvd.ParamC); + cdvd.mg_size += cdvd.ParamC; + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + } + break; + + case 0x8E: // sceMgReadData + SetResultSize(min(16, cdvd.mg_size)); + memcpy_amd(cdvd.Result, cdvd.mg_buffer, cdvd.ResultC); + cdvd.mg_size -= cdvd.ResultC; + memcpy_amd(cdvd.mg_buffer, cdvd.mg_buffer+cdvd.ResultC, cdvd.mg_size); + break; + + case 0x88: // secrman: __mechacon_auth_0x88 //for now it is the same; so, fall;) + case 0x8F: // secrman: __mechacon_auth_0x8F + SetResultSize(1);//in:0 + if (cdvd.mg_datatype == 1){// header data + int bit_ofs, i; + + if (cdvd.mg_maxsize != cdvd.mg_size) goto fail_pol_cal; + if (cdvd.mg_size < 0x20) goto fail_pol_cal; + if (cdvd.mg_size != *(u16*)&cdvd.mg_buffer[0x14]) goto fail_pol_cal; + SysPrintf("[MG] ELF_size=0x%X Hdr_size=0x%X unk=0x%X flags=0x%X count=%d zones=", + *(u32*)&cdvd.mg_buffer[0x10], *(u16*)&cdvd.mg_buffer[0x14], *(u16*)&cdvd.mg_buffer[0x16], + *(u16*)&cdvd.mg_buffer[0x18], *(u16*)&cdvd.mg_buffer[0x1A]); + for (i=0; i<8; i++) + if (cdvd.mg_buffer[0x1C] & (1<> 0) & 0xFF; + cdvd.Result[2] = (cdvd.mg_size >> 8) & 0xFF; + break; + + case 0x92: // sceMgWriteDatainLength + cdvd.mg_size = 0; + cdvd.mg_datatype = 0;//data (encrypted) + cdvd.mg_maxsize = cdvd.Param[0] | (((int)cdvd.Param[1])<<8); + SetResultSize(1);//in:2 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + + case 0x93: // sceMgWriteDataoutLength + SetResultSize(1);//in:2 + if (((cdvd.Param[0] | (((int)cdvd.Param[1])<<8)) == cdvd.mg_size) && (cdvd.mg_datatype == 0)){ + cdvd.mg_maxsize = 0; // don't allow any write + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + }else + cdvd.Result[0] = 0x80; + break; + + case 0x94: // sceMgReadKbit - read first half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kbit, 8); + break; + + case 0x95: // sceMgReadKbit2 - read second half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kbit+8, 8); + break; + + case 0x96: // sceMgReadKcon - read first half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kcon, 8); + break; + + case 0x97: // sceMgReadKcon2 - read second half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kcon+8, 8); + break; + + default: + // fake a 'correct' command + SysPrintf("SCMD Unknown %x\n", rt); + SetResultSize(1); //in:0 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + } + //SysPrintf("SCMD - %x\n", rt); + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite17(u8 rt) { // SDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite17(SDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite18(u8 rt) { // SDATAOUT +#ifdef CDR_LOG + CDR_LOG("cdvdWrite18(SDataOut) %x\n", rt); +#endif +} + +void cdvdWrite3A(u8 rt) { // DEC-SET +#ifdef CDR_LOG + CDR_LOG("cdvdWrite3A(DecSet) %x\n", rt); +#endif + cdvd.decSet = rt; + SysPrintf("DecSet Write: %02X\n", cdvd.decSet); +} + +static int mg_BIToffset(u8 *buffer){ + int i, ofs = 0x20; for (i=0; i<*(u16*)&buffer[0x1A]; i++)ofs+=0x10; + if (*(u16*)&buffer[0x18] & 1)ofs+=buffer[ofs]; + if ((*(u16*)&buffer[0x18] & 0xF000)==0)ofs+=8; + return ofs + 0x20; +} diff --git a/CDVD.h b/CDVD.h new file mode 100644 index 0000000000..60e201ccbb --- /dev/null +++ b/CDVD.h @@ -0,0 +1,144 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDVD_H__ +#define __CDVD_H__ + +#include "PsxCommon.h" + +typedef struct { + u8 status; + u8 second; + u8 minute; + u8 hour; + u8 pad; + u8 day; + u8 month; + u8 year; +} cdvdRTC; + +typedef struct { + u8 nCommand; + u8 Ready; + u8 Error; + u8 PwOff; + u8 Status; + u8 Type; + u8 sCommand; + u8 sDataIn; + u8 sDataOut; + u8 HowTo; + + u8 Param[32]; + u8 Result[32]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + + u8 CBlockIndex; + u8 COffset; + u8 CReadWrite; + u8 CNumBlocks; + + int RTCcount; + cdvdRTC RTC; + + u32 Sector; + int nSectors; + int Readed; + int Reading; + int ReadMode; + int BlockSize; + int Speed; + int RetryCnt; + int RetryCntP; + int RErr; + int SpindlCtrl; + + u8 Key[16]; + u8 KeyXor; + u8 decSet; + + u8 mg_buffer[65536]; + int mg_size; + int mg_maxsize; + int mg_datatype;//0-data(encrypted); 1-header + u8 mg_kbit[16];//last BIT key 'seen' + u8 mg_kcon[16];//last content key 'seen' +// char Unused[4096]; +} cdvdStruct; + +extern cdvdStruct cdvd; + +void cdvdReset(); +void cdvdReadTimeRcnt(); +void cdvdVsync(); +int cdvdInterrupt(); +int cdvdFreeze(gzFile f, int Mode); +int cdvdReadInterrupt(); +void cdvdNewDiskCB(); +u8 cdvdRead04(void); +u8 cdvdRead05(void); +u8 cdvdRead06(void); +u8 cdvdRead07(void); +u8 cdvdRead08(void); +u8 cdvdRead0A(void); +u8 cdvdRead0B(void); +u8 cdvdRead0C(void); +u8 cdvdRead0D(void); +u8 cdvdRead0E(void); +u8 cdvdRead0F(void); +u8 cdvdRead13(void); +u8 cdvdRead15(void); +u8 cdvdRead16(void); +u8 cdvdRead17(void); +u8 cdvdRead18(void); +u8 cdvdRead20(void); +u8 cdvdRead21(void); +u8 cdvdRead22(void); +u8 cdvdRead23(void); +u8 cdvdRead24(void); +u8 cdvdRead28(void); +u8 cdvdRead29(void); +u8 cdvdRead2A(void); +u8 cdvdRead2B(void); +u8 cdvdRead2C(void); +u8 cdvdRead30(void); +u8 cdvdRead31(void); +u8 cdvdRead32(void); +u8 cdvdRead33(void); +u8 cdvdRead34(void); +u8 cdvdRead38(void); +u8 cdvdRead39(void); +u8 cdvdRead3A(void); +void cdvdWrite04(u8 rt); +void cdvdWrite05(u8 rt); +void cdvdWrite06(u8 rt); +void cdvdWrite07(u8 rt); +void cdvdWrite08(u8 rt); +void cdvdWrite0A(u8 rt); +void cdvdWrite0F(u8 rt); +void cdvdWrite14(u8 rt); +void cdvdWrite16(u8 rt); +void cdvdWrite17(u8 rt); +void cdvdWrite18(u8 rt); +void cdvdWrite3A(u8 rt); + +#endif /* __CDVD_H__ */ diff --git a/CDVDiso.c b/CDVDiso.c new file mode 100644 index 0000000000..4f8ac8798f --- /dev/null +++ b/CDVDiso.c @@ -0,0 +1,834 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + * Fixed CdRead by linuzappz + */ + +#include +#ifdef __LINUX__ +#define strnicmp strncasecmp +#endif + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +struct dir_toc_data{ + unsigned int start_LBA; + unsigned int num_sectors; + unsigned int num_entries; + unsigned int current_entry; + unsigned int current_sector; + unsigned int current_sector_offset; + unsigned int inc_dirs; + unsigned char extension_list[128+1]; +}; + +//static u8 cdVolDescriptor[2048]; +static struct dir_toc_data getDirTocData; +static struct cdVolDesc CDVolDesc; + +void _splitpath2(const char *constpath, char *dir, char *fname){ + // 255 char max path-length is an ISO9660 restriction + // we must change this for Joliet or relaxed iso restriction support + static char pathcopy[1024+1]; + + char* slash; + + strncpy(pathcopy, constpath, 1024); + + slash = strrchr (pathcopy, '/'); + + // if the path doesn't contain a '/' then look for a '\' + if (!slash) + slash = strrchr (pathcopy, (int)'\\'); + + // if a slash was found + if (slash != NULL) + { + // null terminate the path + slash[0] = 0; + // and copy the path into 'dir' + strncpy(dir, pathcopy, 1024); + dir[255]=0; + + // copy the filename into 'fname' + strncpy(fname, slash+1, 128); + fname[128]=0; + } + else + { + dir[0] = 0; + + strncpy(fname, pathcopy, 128); + fname[128]=0; + } + +} + +// Used in findfile +int tolower(int c); +int strcasecmp(const char *s1, const char *s2){ + while (*s1 != '\0' && tolower(*s1) == tolower(*s2)) + { + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} + +// Copy a TOC Entry from the CD native format to our tidier format +void TocEntryCopy(struct TocEntry* tocEntry, struct dirTocEntry* internalTocEntry){ + int i; + int filenamelen; + + tocEntry->fileSize = internalTocEntry->fileSize; + tocEntry->fileLBA = internalTocEntry->fileLBA; + tocEntry->fileProperties = internalTocEntry->fileProperties; + memcpy(tocEntry->date, internalTocEntry->dateStamp, 7); + + if (CDVolDesc.filesystemType == 2){ + // This is a Joliet Filesystem, so use Unicode to ISO string copy + + filenamelen = internalTocEntry->filenameLength/2; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + for (i=0; i < filenamelen; i++) + tocEntry->filename[i] = internalTocEntry->filename[(i<<1)+1]; + + tocEntry->filename[filenamelen] = 0; + } + else{ + filenamelen = internalTocEntry->filenameLength; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + // use normal string copy + strncpy(tocEntry->filename,internalTocEntry->filename,128); + tocEntry->filename[filenamelen] = 0; + } +} + +// Check if a TOC Entry matches our extension list +int TocEntryCompare(char* filename, char* extensions){ + static char ext_list[129]; + + char* token; + + char* ext_point; + + strncpy(ext_list,extensions,128); + ext_list[128]=0; + + token = strtok( ext_list, " ," ); + while( token != NULL ) + { + // if 'token' matches extension of 'filename' + // then return a match + ext_point = strrchr(filename,'.'); + + if (strnicmp(ext_point, token, strlen(token)) == 0) + return (TRUE); + + /* Get next token: */ + token = strtok( NULL, " ," ); + } + + // If not match found then return FALSE + return (FALSE); + +} + +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ + +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + int rmode; + + switch (mode->datapattern) { + case CdSecS2048: + rmode = CDVD_MODE_2048; break; + case CdSecS2328: + rmode = CDVD_MODE_2328; break; + case CdSecS2340: + rmode = CDVD_MODE_2340; break; + default: + return 0; + } + + for (i=0; idatapattern){ + case CdSecS2048: + memcpy((void*)((uptr)buf+2048*i), buff, 2048);break;//only data + case CdSecS2328: + memcpy((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub + case CdSecS2340: + memcpy((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync + } + } + return 1; +} + +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + + for (i=lsn; i<(lsn+sectors); i++){ + if (CDVDreadTrack(i, CDVD_MODE_2048)==-1) + return 0; + buff = CDVDgetBuffer(); + if (buff==NULL) return 0; + +// switch (mode->datapattern){ +// case CdSecS2064: + ((u32*)buf)[0] = i + 0x30000; + memcpy((u8*)buf+12, buff, 2048); + (u8*)buf+= 2064; break; +// default: +// return 0; +// } + } + + return 1; +} + +/************************************************************** +* The functions below are not exported for normal file-system * +* operations, but are used by the file-system operations, and * +* may also be exported for use via RPC * +**************************************************************/ + +int CDVD_GetVolumeDescriptor(void){ + // Read until we find the last valid Volume Descriptor + int volDescSector; + + static struct cdVolDesc localVolDesc; + +#ifdef DEBUG + printf("CDVD_GetVolumeDescriptor called\n"); +#endif + + for (volDescSector = 16; volDescSector<20; volDescSector++) + { + CdRead(volDescSector,1,&localVolDesc,&cdReadMode); +// CdSync(0x00); + + // If this is still a volume Descriptor + if (strncmp(localVolDesc.volID, "CD001", 5) == 0) + { + if ((localVolDesc.filesystemType == 1) || + (localVolDesc.filesystemType == 2)) + { + memcpy(&CDVolDesc, &localVolDesc, sizeof(struct cdVolDesc)); + } + } + else + break; + } + +#ifdef DEBUG + if (CDVolDesc.filesystemType == 1) + printf("CD FileSystem is ISO9660\n"); + else if (CDVolDesc.filesystemType == 2) + printf("CD FileSystem is Joliet\n"); + else printf("Could not detect CD FileSystem type\n"); +#endif +// CdStop(); + + return TRUE; +} + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry){ + static char filename[128+1]; + static char pathname[1024+1]; + static char toc[2048]; + char* dirname; + + + static struct TocEntry localTocEntry; // used for internal checking only + + int found_dir; + + int num_dir_sectors; + int current_sector; + + int dir_lba; + + struct dirTocEntry* tocEntryPointer; + +#ifdef DEBUG + printf("CDVD_findfile called\n"); +#endif + + //make sure we have good cdReadMode + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; + + _splitpath2(fname, pathname, filename); + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + + while( dirname != NULL ) + { + found_dir = FALSE; +/* + while(tocEntryPointer->length > 0) + { + // while there are still more directory entries then search through + // for the one we want + + if (tocEntryPointer->fileProperties & 0x02) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcasecmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } +*/ + while(1) + { + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) + { + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else + { + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + + if (tocEntryPointer->fileProperties & 0x02) + { + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + { + printf("CDVD_findfile: could not find dir\n"); + return -1; + } + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; //round up fix + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + +#ifdef DEBUG + printf("CDVD_findfile: found dir, now looking for file\n"); +#endif + + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + dir_lba = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + while (num_dir_sectors > 0) + { + while(tocEntryPointer->length != 0) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if ((strnicmp(localTocEntry.filename, filename, strlen(filename)) == 0) || + ((filename[strlen(filename)-2] == ';') && + (localTocEntry.filename[strlen(localTocEntry.filename)-2] == ';') && + (strnicmp(localTocEntry.filename, filename, strlen(filename)-2) == 0))) + { + // if the filename matches then copy the toc Entry + tocEntry->fileLBA = localTocEntry.fileLBA; + tocEntry->fileProperties = localTocEntry.fileProperties; + tocEntry->fileSize = localTocEntry.fileSize; + + strcpy(tocEntry->filename, localTocEntry.filename); + memcpy(tocEntry->date, localTocEntry.date, 7); + +#ifdef DEBUG + printf("CDVD_findfile: found file\n"); +#endif + + return TRUE; + } + + (char*)tocEntryPointer += tocEntryPointer->length; + } + + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + dir_lba++; + + if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){ + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + } + +#ifdef DEBUG + printf("CDVD_findfile: could not find file\n"); +#endif + + return FALSE; +} + +// This is the RPC-ready function which takes the request to start the tocEntry retrieval +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){ +// int dir_depth = 1; + static char toc[2048]; + char* dirname; + int found_dir; + int num_dir_sectors; + unsigned int toc_entry_num; + struct dirTocEntry* tocEntryPointer; + static struct TocEntry localTocEntry; + int current_sector; + + // store the extension list statically for the retrieve function + strncpy(getDirTocData.extension_list, extensions, 128); + getDirTocData.extension_list[128]=0; + + getDirTocData.inc_dirs = inc_dirs; + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"\n", pathname); +#endif + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + // use strtok to get the next dir name + + // if there isnt one, then assume we want the LBA + // for the current one, and exit the while loop + + // if there is another dir name then increment dir_depth + // and look through dir table entries until we find the right name + // if we dont find the right name + // before finding an entry at a higher level (lower num), then return nothing + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + while( dirname != NULL ){ + found_dir = FALSE; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) { + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else{ + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + if (tocEntryPointer->fileProperties & 0x02){ + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0){ + // if the name matches then we've found the directory + found_dir = TRUE; +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d\n",dirname,current_sector); + RPC_LOG("[RPC: ] LBA of found subdirectory = %d\n",localTocEntry.fileLBA); +#endif + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + return -1; + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // We know how much data we need to read in from the DirTocHeader + // but we need to read in at least 1 sector before we can get this value + + // Now we need to COUNT the number of entries (dont do anything with info at this point) + // so set the tocEntryPointer to point to the first actual file entry + + // This is a bit of a waste of reads since we're not actually copying the data out yet, + // but we dont know how big this TOC might be, so we cant allocate a specific size + + (char*)tocEntryPointer = toc; + + // Need to STORE the start LBA and number of Sectors, for use by the retrieve func. + getDirTocData.start_LBA = localTocEntry.fileLBA; + getDirTocData.num_sectors = (tocEntryPointer->fileSize+2047) >> 11; + getDirTocData.num_entries = 0; + getDirTocData.current_entry = 0; + getDirTocData.current_sector = getDirTocData.start_LBA; + getDirTocData.current_sector_offset = 0; + + num_dir_sectors = getDirTocData.num_sectors; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + toc_entry_num=0; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)){ + // decrease the number of dirs remaining + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + +// continue; + } + else{ + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + return (toc_entry_num); + } + } + + // We've found a file/dir in this directory + // now check if it matches our extension list (if there is one) + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if (localTocEntry.fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs){ + toc_entry_num++; + } + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(localTocEntry.filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + } + else{ + toc_entry_num++; + } + } + + (char*)tocEntryPointer += tocEntryPointer->length; + + } + + + // THIS SHOULD BE UNREACHABLE - + // since we are trying to count ALL matching entries, rather than upto a limit + + + // STORE total number of TOC entries + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + + + // we've reached the toc entry limit, so return how many we've done + return (toc_entry_num); + +} + +// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries +// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries){ + static char toc[2048]; + int toc_entry_num; + + struct dirTocEntry* tocEntryPointer; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + if (getDirTocData.current_entry == 0){ + // if this is the first read then make sure we point to the first real entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + getDirTocData.current_sector_offset = (char*)tocEntryPointer - toc; + } + else{ + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + + if (req_entries > 128) + req_entries = 128; + + for (toc_entry_num=0; toc_entry_num < req_entries;){ + if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){ + // decrease the number of dirs remaining + getDirTocData.num_sectors--; + + if (getDirTocData.num_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + getDirTocData.current_sector_offset = 0; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + +// continue; + } + else{ + return (toc_entry_num); + } + } + + // This must be incremented even if the filename doesnt match extension list + getDirTocData.current_entry++; + + // We've found a file in this directory + // now check if it matches our extension list (if there is one) + + // Copy the entry regardless, as it makes the comparison easier + // if it doesn't match then it will just be overwritten + TocEntryCopy(&tocEntry[toc_entry_num], tocEntryPointer); + + if (tocEntry[toc_entry_num].fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs) { + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + + } + else{ + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + } +/* + if (strlen(getDirTocData.extension_list) > 0) + { + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE) + { + + // increment this here, rather than in the main for loop + // since this should count the number of matching entries + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else + { + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } +*/ + } + return (toc_entry_num); +} diff --git a/CDVDiso.h b/CDVDiso.h new file mode 100644 index 0000000000..72b0552280 --- /dev/null +++ b/CDVDiso.h @@ -0,0 +1,131 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISO_H__ +#define __CDVDISO_H__ + +#include "CDVDlib.h" + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs); +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries); + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTableEntry +{ + u8 dirNameLength; + u8 reserved; + u32 dirTOCLBA; + u16 dirDepth; + u8 dirName[32]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTocEntry +{ + short length; + unsigned int fileLBA; + unsigned int fileLBA_bigend; + unsigned int fileSize; + unsigned int fileSize_bigend; + unsigned char dateStamp[6]; + unsigned char reserved1; + unsigned char fileProperties; + unsigned char reserved2[6]; + unsigned char filenameLength; + unsigned char filename[128]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif // This is the internal format on the CD +// TocEntry structure contains only the important stuff needed for export + +#if defined(__WIN32__) +#pragma pack() +#endif + +#endif//__CDVDISO_H__ diff --git a/CDVDisodrv.c b/CDVDisodrv.c new file mode 100644 index 0000000000..a415367980 --- /dev/null +++ b/CDVDisodrv.c @@ -0,0 +1,263 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#include + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +CdRMode cdReadMode; + +struct fdtable{ +//int fd; + int fileSize; + int LBA; + int filePos; +}; + +static struct fdtable fd_table[16]; +static int fd_used[16]; +static int files_open=0; +static int inited=FALSE; + +/************************************************************* +* The functions below are the normal file-system operations, * +* used to provide a standard filesystem interface * +*************************************************************/ + +////////////////////////////////////////////////////////////////////// +// CDVDFS_init +// called by 80000592 sceCdInit() +////////////////////////////////////////////////////////////////////// +void CDVDFS_init(){ + + if (inited) return;//might change in the future as a param; forceInit/Reset + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:init] CDVD Filesystem v1.00\n"); + RPC_LOG("[CDVDisodrv ] \tby A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)\n"); + RPC_LOG("[CDVDisodrv ] Initializing '%s' file driver.\n", "cdfs"); +#endif + + //CdInit(0); already called by plugin loading system ;) + + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; //isofs driver only needs + //2KB sectors + + memset(fd_table, 0, sizeof(fd_table)); + memset(fd_used, 0, 16*sizeof(int)); + + inited = TRUE; + + return; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_open +// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_open(char *name, int mode){ + register int j; + static struct TocEntry tocEntry; + + // check if the file exists + if (CDVD_findfile(name, &tocEntry) != TRUE) + return -1; + + if(mode != 1) return -2; //SCE_RDONLY + + // set up a new file descriptor + for(j=0; j < 16; j++) if(fd_used[j] == 0) break; + if(j >= 16) return -3; + + fd_used[j] = 1; + files_open++; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:open] internal fd=%d\n", j); +#endif + + fd_table[j].fileSize = tocEntry.fileSize; + fd_table[j].LBA = tocEntry.fileLBA; + fd_table[j].filePos = 0; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv ] tocEntry.fileSize = %d\n",tocEntry.fileSize); +#endif + + return j; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_lseek +// called by 80000001 fileio_lseek for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_lseek(int fd, int offset, int whence){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:lseek] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + switch(whence){ + case SEEK_SET: + fd_table[fd].filePos = offset; + break; + + case SEEK_CUR: + fd_table[fd].filePos += offset; + break; + + case SEEK_END: + fd_table[fd].filePos = fd_table[fd].fileSize + offset; + break; + + default: + return -1; + } + + if (fd_table[fd].filePos < 0) + fd_table[fd].filePos = 0; + + if (fd_table[fd].filePos > fd_table[fd].fileSize) + fd_table[fd].filePos = fd_table[fd].fileSize; + + return fd_table[fd].filePos; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_read +// called by 80000001 fileio_read for devices: "cdrom:", "cdrom0:", "cdfs:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_read( int fd, char *buffer, int size ){ +// int start_sector; + int off_sector; +// int num_sectors; + + //static char local_buffer[2024*2048]; //4MB + static char lb[2048]; //2KB + //Start, Aligned, End + int ssector, asector, esector; + int ssize=0, asize, esize; + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + // A few sanity checks + if (fd_table[fd].filePos > fd_table[fd].fileSize){ + // We cant start reading from past the beginning of the file + return 0; // File exists but we couldnt read anything from it + } + + if ((fd_table[fd].filePos + size) > fd_table[fd].fileSize) + size = fd_table[fd].fileSize - fd_table[fd].filePos; + + // Now work out where we want to start reading from + asector = ssector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + if (off_sector){ + ssize = min(2048 - off_sector, size); + size -= ssize; + asector++; + } + asize = size & 0xFFFFF800; + esize = size & 0x000007FF; + esector=asector + (asize >> 11); + size += ssize; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n", ssector, esector-(esize==0)); +#endif + + if (ssize){ if (CdRead(ssector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer, lb + off_sector, ssize); + } + if (asize) if (CdRead(asector, asize >> 11, buffer+ssize, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + if (esize){ if (CdRead(esector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer+ssize+asize, lb, esize); + } +/*********************** + // Now work out where we want to start reading from + start_sector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + num_sectors = ((off_sector + size) >> 11) + 1; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n",start_sector,start_sector+num_sectors); +#endif + + // Read the data (we only ever get 16KB max request at once) + if (CdRead(start_sector, num_sectors, local_buffer, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + //RPC_LOG("sector = %d, start sector = %d\n",sector,start_sector); + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + //CdSync(0); hm, a wait function maybe... + + memcpy(buffer,local_buffer+off_sector,size); +**************************/ + fd_table[fd].filePos += size; + + return (size); +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_write +// called by 80000001 fileio_write for devices: "cdrom:", "cdrom0:" +// hehe, this ain't a CD writing option :D +////////////////////////////////////////////////////////////////////// +int CDVDFS_write( int fd, char * buffer, int size ){ + if(size == 0) return 0; + else return -1; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_close +// called by 80000001 fileio_close for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_close( int fd){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] internal fd %d\n", fd); +#endif + + fd_used[fd] = 0; + files_open--; + + return 0; +} + diff --git a/CDVDisodrv.h b/CDVDisodrv.h new file mode 100644 index 0000000000..dcf8545a86 --- /dev/null +++ b/CDVDisodrv.h @@ -0,0 +1,22 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISODRV_H__ +#define __CDVDISODRV_H__ + +//#include "Common.h" +#include "CDVDlib.h" + +extern CdRMode cdReadMode; + +/* Filing-system exported functions */ +void CDVDFS_init(); +int CDVDFS_open(char *name, int mode); +int CDVDFS_lseek(int fd, int offset, int whence); +int CDVDFS_read( int fd, char * buffer, int size ); +int CDVDFS_write( int fd, char * buffer, int size ); +int CDVDFS_close( int fd); + +#endif//__CDVDISODRV_H__ diff --git a/CDVDlib.h b/CDVDlib.h new file mode 100644 index 0000000000..f4519818e7 --- /dev/null +++ b/CDVDlib.h @@ -0,0 +1,185 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Linux kernel headers + * Modified by Florin for PCSX2 emu + */ + +#ifndef _CDVDLIB_H +#define _CDVDLIB_H + +#include "Common.h" + +// Macros for READ Data pattan +#define CdSecS2048 0 // sector size 2048 +#define CdSecS2328 1 // sector size 2328 +#define CdSecS2340 2 // sector size 2340 + +//#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +//#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ +//#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +//#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +//#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ + +/* + * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, + * 2340, or 2352 bytes long. + * Sector types of the standard CD-ROM data formats: + * + * format sector type user data size (bytes) + * ----------------------------------------------------------------------------- + * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW) + * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE) + * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0) + * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE) + * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) + * + * + * The layout of the standard CD-ROM data formats: + * ----------------------------------------------------------------------------- + * - audio (red): | audio_sample_bytes | + * | 2352 | + * + * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | + * | 12 - 4 - 2048 - 4 - 8 - 276 | + * + * - data (yellow, mode2): | sync - head - data | + * | 12 - 4 - 2336 | + * + * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | + * | 12 - 4 - 8 - 2048 - 4 - 276 | + * + * - XA data (green, mode2 form2): | sync - head - sub - data - Spare | + * | 12 - 4 - 8 - 2324 - 4 | + * + */ + +// Macros for Spindle control +#define CdSpinMax 0 +#define CdSpinNom 1 // Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. +#define CdSpinStm 0 // Recommended stream rotation speed. + +// Macros for TrayReq +#define CdTrayOpen 0 +#define CdTrayClose 1 +#define CdTrayCheck 2 + +/* + * Macros for sceCdGetDiskType() //comments translated from japanese;) + */ +#define SCECdIllgalMedia 0xff + /* ILIMEDIA (Illegal Media) + A non-PS / non-PS2 Disc. */ +#define SCECdDVDV 0xfe + /* DVDV (DVD Video) + A non-PS / non-PS2 Disc, but a DVD Video Disc */ +#define SCECdCDDA 0xfd + /* CDDA (CD DA) + A non-PS / non-PS2 Disc that include a DA track */ +#define SCECdPS2DVD 0x14 + /* PS2DVD PS2 consumer DVD. */ +#define SCECdPS2CDDA 0x13 + /* PS2CDDA PS2 consumer CD that includes a DA track */ +#define SCECdPS2CD 0x12 + /* PS2CD PS2 consumer CD that does not include a DA track */ +#define SCECdPSCDDA 0x11 + /* PSCDDA PS CD that includes a DA track */ +#define SCECdPSCD 0x10 + /* PSCD PS CD that does not include a DA track */ +#define SCECdDETCT 0x01 + /* DETCT (Detecting) Disc distinction action */ +#define SCECdNODISC 0x00 + /* NODISC (No disc) No disc entered */ + +/* + * Media mode + */ +#define SCECdCD 1 +#define SCECdDVD 2 + +typedef struct { + u8 stat; // 0: normal. Any other: error + u8 second; // second (BCD value) + u8 minute; // minute (BCD value) + u8 hour; // hour (BCD value) + u8 week; // week (BCD value) + u8 day; // day (BCD value) + u8 month; // month (BCD value) + u8 year; // year (BCD value) +} CdCLOCK; + +typedef struct { + u32 lsn; // Logical sector number of file + u32 size; // File size (in bytes) + char name[16]; // Filename + u8 date[8]; // 1th: Seconds + // 2th: Minutes + // 3th: Hours + // 4th: Date + // 5th: Month + // 6th 7th: Year (4 digits) +} CdlFILE; + +typedef struct { + u8 minute; // Minutes + u8 second; // Seconds + u8 sector; // Sector + u8 track; // Track number +} CdlLOCCD; + +typedef struct { + u8 trycount; // Read try count (No. of error retries + 1) (0 - 255) + u8 spindlctrl; // SCECdSpinStm: Recommended stream rotation speed. + // SCECdSpinNom: Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. + u8 datapattern; // SCECdSecS2048: Data size 2048 bytes + // SCECdSecS2328: 2328 bytes + // SCECdSecS2340: 2340 bytes + u8 pad; // Padding data produced by alignment. +} CdRMode; + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct TocEntry +{ + u32 fileLBA; + u32 fileSize; + u8 fileProperties; + u8 padding1[3]; + u8 filename[128+1]; + u8 date[7]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +#if defined(__WIN32__) +#pragma pack() +#endif + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +/* +int CdBreak(void); +int CdCallback( void (*func)() ); +int CdDiskReady(int mode); +int CdGetDiskType(void); +int CdGetError(void); +u32 CdGetReadPos(void); +int CdGetToc(u8 *toc); +int CdInit(int init_mode); +CdlLOCCD *CdIntToPos(int i, CdlLOCCD *p); +int CdPause(void); +int CdPosToInt(CdlLOCCD *p);*/ +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +/*int CdReadClock(CdCLOCK *rtc); +int CdSearchFile (CdlFILE *fp, const char *name); +int CdSeek(u32 lsn); +int CdStandby(void); +int CdStatus(void); +int CdStop(void); +int CdSync(int mode); +int CdTrayReq(int mode, u32 *traycnt); +*/ +#endif // _CDVDLIB_H diff --git a/COP0.c b/COP0.c new file mode 100644 index 0000000000..53f67b96cc --- /dev/null +++ b/COP0.c @@ -0,0 +1,318 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +extern BOOL bExecBIOS; + +void COP0() { + Int_COP0PrintTable[_Rs_](); +} + +void COP0_BC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03](); +} + +void COP0_Func() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0C0PrintTable[_Funct_](); +} + +void COP0_Unknown() { +#ifdef CPU_LOG + CPU_LOG("COP0 Unknown opcode called\n"); +#endif +} + +void UpdateCP0Status() { + u32 value = cpuRegs.CP0.n.Status.val; + + if (value & 0x06 || + (value & 0x18) == 0) { // Kernel Mode (KSU = 0 | EXL = 1 | ERL = 1)*/ + memSetKernelMode(); // Kernel memory always + } else { // User Mode + memSetUserMode(); + } + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)cpuTestHwInts(); +} + +void WriteCP0Status(u32 value) { + cpuRegs.CP0.n.Status.val = value; + UpdateCP0Status(); +} + +extern u32 s_iLastCOP0Cycle; + +void MFC0() { + if (!_Rt_) return; +#ifdef COP0_LOG + if (_Rd_ != 9) { COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); } +#endif + + if( _Rd_ == 9 ) { + // update + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + } + cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.CP0.r[_Rd_]; +} + +void MTC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + switch (_Rd_) { + case 12: WriteCP0Status(cpuRegs.GPR.r[_Rt_].UL[0]); break; + case 9: s_iLastCOP0Cycle = cpuRegs.cycle; cpuRegs.CP0.r[9] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + default: cpuRegs.CP0.r[_Rd_] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + } +} + +int CPCOND0() { + if(((psHu16(DMAC_STAT) & psHu16(DMAC_PCR)) & 0x3ff) == (psHu16(DMAC_PCR) & 0x3ff)) return 1; + else return 0; +} + +//#define CPCOND0 1 + +#define BC0(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC0F() { + BC0(== 0); +} + +void BC0T() { + BC0(== 1); +} + +#define BC0L(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC0FL() { + BC0L(== 0); +} + +void BC0TL() { + BC0L(== 1); +} + +void TLBR() { +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + int i = cpuRegs.CP0.n.Index&0x1f; + +// if( !bExecBIOS ) +// __Log("TLBR %d\n", cpuRegs.CP0.n.Index&0x1f); + + SysPrintf("COP0_TLBR\n"); + cpuRegs.CP0.n.PageMask = tlb[i].PageMask; + cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi&~(tlb[i].PageMask|0x1f00); + cpuRegs.CP0.n.EntryLo0 = (tlb[i].EntryLo0&~1)|((tlb[i].EntryHi>>12)&1); + cpuRegs.CP0.n.EntryLo1 =(tlb[i].EntryLo1&~1)|((tlb[i].EntryHi>>12)&1); +} + +void ClearTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void WriteTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + tlb[i].PageMask = cpuRegs.CP0.n.PageMask; + tlb[i].EntryHi = cpuRegs.CP0.n.EntryHi; + tlb[i].EntryLo0 = cpuRegs.CP0.n.EntryLo0; + tlb[i].EntryLo1 = cpuRegs.CP0.n.EntryLo1; + + tlb[i].Mask = (cpuRegs.CP0.n.PageMask >> 13) & 0xfff; + tlb[i].nMask = (~tlb[i].Mask) & 0xfff; + tlb[i].VPN2 = ((cpuRegs.CP0.n.EntryHi >> 13) & (~tlb[i].Mask)) << 13; + tlb[i].ASID = cpuRegs.CP0.n.EntryHi & 0xfff; + tlb[i].G = cpuRegs.CP0.n.EntryLo0 & cpuRegs.CP0.n.EntryLo1 & 0x1; + tlb[i].PFN0 = (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN0|= (0x80000000); + tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN1|= (0x80000000); + if (tlb[i].VPN2 == 0x70000000) return; + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void TLBWI() { + int j = cpuRegs.CP0.n.Index & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWI %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWI %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBWR() { + int j = cpuRegs.CP0.n.Random & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWR %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBP() { + int i; + + + union { + struct { + u32 VPN2:19; + u32 VPN2X:2; + u32 G:3; + u32 ASID:8; + } s; + u32 u; + } EntryHi32; + + if( !bExecBIOS ) + __Log("TLBP %x\n", cpuRegs.CP0.n.EntryHi); + + EntryHi32.u=cpuRegs.CP0.n.EntryHi; + + cpuRegs.CP0.n.Index=0xFFFFFFFF; + for(i=0;i<48;i++){ + if(tlb[i].VPN2==((~tlb[i].Mask)&(EntryHi32.s.VPN2)) + &&((tlb[i].G&1)||((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) { + cpuRegs.CP0.n.Index=i; + break; + } + } + if(cpuRegs.CP0.n.Index == 0xFFFFFFFF) cpuRegs.CP0.n.Index = 0x80000000; +} + +void ERET() { + if (cpuRegs.CP0.n.Status.b.ERL) { + cpuRegs.pc = cpuRegs.CP0.n.ErrorEPC; + cpuRegs.CP0.n.Status.b.ERL = 0; + } else { + cpuRegs.pc = cpuRegs.CP0.n.EPC; + cpuRegs.CP0.n.Status.b.EXL = 0; + } + UpdateCP0Status(); + intSetBranch(); +} + +void DI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 0; + UpdateCP0Status(); + } +} + +void EI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 1; + UpdateCP0Status(); + } +} + diff --git a/COP0.h b/COP0.h new file mode 100644 index 0000000000..30ad0633c9 --- /dev/null +++ b/COP0.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COP0_H__ +#define __COP0_H__ + +void WriteCP0Status(u32 value); +void UpdateCP0Status(); +void WriteTLB(int i); +void ClearTLB(int i); + +#endif /* __COP0_H__ */ diff --git a/Cache.c b/Cache.c new file mode 100644 index 0000000000..305a666de2 --- /dev/null +++ b/Cache.c @@ -0,0 +1,355 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "Cache.h" + +/*_cacheS pCache[64]; +int getFreeCache(u32 mem, int mode, int * way) { + u8 * out; + u32 paddr; + u32 taddr[2]; + u8 * t; + int number; + int i = (mem >> 6) & 0x3F; + + paddr = memLUTR[mem >> 12]; + taddr[0] = memLUTW[pCache[i].tag[0]>>12]; + taddr[1] = memLUTW[pCache[i].tag[1]>>12]; + + if (taddr[0] == paddr && (pCache[i].tag[0] & 0x20)) + { + *way = 0; + return i; + }else if(taddr[1] == paddr && (pCache[i].tag[1] & 0x20)) + { + *way = 1; + return i; + } + + number = ((pCache[i].tag[0]>>4) & 1) ^ ((pCache[i].tag[1]>>4) & 1); + + if(pCache[i].tag[number] & 0x60) // Valid Dirty + { + t = (char *)(taddr[number]); + out = (u8*)(t + (mem & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[i].data[number][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[i].data[number][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[i].data[number][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[i].data[number][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[i].data[number][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[i].data[number][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[i].data[number][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[i].data[number][3].b8._8)[1]; + } + + + + if(mode == 1) + { + pCache[i].tag[number] |= 0x40; // Set Dirty Bit if mode == write + } + + pCache[i].tag[number] &= ~(0xFFFFF000); + pCache[i].tag[number] |= ((mem>>12) & 0xFFFFF) << 12; + + + t = (u8 *)paddr; + out= (u8*)(t + (mem & 0xFC0)); + ((u64*)pCache[i].data[number][0].b8._8)[0] = ((u64*)out)[0]; + ((u64*)pCache[i].data[number][0].b8._8)[1] = ((u64*)out)[1]; + ((u64*)pCache[i].data[number][1].b8._8)[0] = ((u64*)out)[2]; + ((u64*)pCache[i].data[number][1].b8._8)[1] = ((u64*)out)[3]; + ((u64*)pCache[i].data[number][2].b8._8)[0] = ((u64*)out)[4]; + ((u64*)pCache[i].data[number][2].b8._8)[1] = ((u64*)out)[5]; + ((u64*)pCache[i].data[number][3].b8._8)[0] = ((u64*)out)[6]; + ((u64*)pCache[i].data[number][3].b8._8)[1] = ((u64*)out)[7]; + + if(pCache[i].tag[number] & 0x10) pCache[i].tag[number] &= ~(0x10); + else pCache[i].tag[number] |= 0x10; + + pCache[i].tag[number] |= 0x20; + *way = number; + return i; +} + +void writeCache8(u32 mem, u8 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)] = value; +} + +void writeCache16(u32 mem, u16 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + *(u16*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache32(u32 mem, u32 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + *(u32*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache64(u32 mem, u64 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + *(u64*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache128(u32 mem, u64 *value) { + int i, number; + + i = getFreeCache(mem,1,&number); + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[0] = value[0]; + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[1] = value[1]; +} + +u8 *readCache(u32 mem) { + int i, number; + + i = getFreeCache(mem,0,&number); + + return pCache[i].data[number][(mem>>4) & 0x3].b8._8; +} + +void CACHE() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + switch (_Rt_) { + case 0x1a: + { + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTR[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef GTE_LOG + GTE_LOG("CACHE DHIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + break; + } + case 0x18: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef GTE_LOG + GTE_LOG("CACHE DHWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + break; + } + case 0x1c: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } +#ifdef GTE_LOG + GTE_LOG("CACHE DHWOIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x40); + break; + } + case 0x16: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; +#ifdef GTE_LOG + GTE_LOG("CACHE DXIN addr %x, index %d, way %d, flag %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + break; + } + case 0x11: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + cpuRegs.CP0.r[28] = *(u32 *)(out+(addr&0xf)); +#ifdef GTE_LOG + GTE_LOG("CACHE DXLDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x10: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + + cpuRegs.CP0.r[28] = 0; + cpuRegs.CP0.r[28] = pCache[index].tag[way]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXLTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x13: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + *(u32*)(&pCache[index].data[way][(addr>>4) & 0x3].b8._8[(addr&0xf)]) = cpuRegs.CP0.r[28]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXSDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x12: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + pCache[index].tag[way] = cpuRegs.CP0.r[28]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXSTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28] & 0x6F); +#endif + break; + } + case 0x14: + { + + u8 * out; + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + +#ifdef GTE_LOG + GTE_LOG("CACHE DXWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Dirty + { + u32 paddr = memLUTW[pCache[index].tag[way] >> 12]; + char * t = (char *)(paddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + break; + } + } +}*/ + +void CACHE() { +} \ No newline at end of file diff --git a/Cache.h b/Cache.h new file mode 100644 index 0000000000..07ed623293 --- /dev/null +++ b/Cache.h @@ -0,0 +1,34 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "Common.h" + +void freeCache(int i); +int getFreeCache(); + +void writeCache8(u32 mem, u8 value); +void writeCache16(u32 mem, u16 value); +void writeCache32(u32 mem, u32 value); +void writeCache64(u32 mem, u64 value); +void writeCache128(u32 mem, u64 *value); +u8 *readCache(u32 mem); + +#endif /* __CACHE_H__ */ diff --git a/CdRom.c b/CdRom.c new file mode 100644 index 0000000000..2f3f1be282 --- /dev/null +++ b/CdRom.c @@ -0,0 +1,1078 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +//THIS ALL IS FOR THE CDROM REGISTERS HANDLING +#include "PsxCommon.h" + +#define CdlSync 0 +#define CdlNop 1 +#define CdlSetloc 2 +#define CdlPlay 3 +#define CdlForward 4 +#define CdlBackward 5 +#define CdlReadN 6 +#define CdlStandby 7 +#define CdlStop 8 +#define CdlPause 9 +#define CdlInit 10 +#define CdlMute 11 +#define CdlDemute 12 +#define CdlSetfilter 13 +#define CdlSetmode 14 +#define CdlGetmode 15 +#define CdlGetlocL 16 +#define CdlGetlocP 17 +#define Cdl18 18 +#define CdlGetTN 19 +#define CdlGetTD 20 +#define CdlSeekL 21 +#define CdlSeekP 22 +#define CdlTest 25 +#define CdlID 26 +#define CdlReadS 27 +#define CdlReset 28 +#define CdlReadToc 30 + +#define AUTOPAUSE 249 +#define READ_ACK 250 +#define READ 251 +#define REPPLAY_ACK 252 +#define REPPLAY 253 +#define ASYNC 254 +/* don't set 255, it's reserved */ + +char *CmdName[0x100]= { + "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", + "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", + "CdlStop", "CdlPause", "CdlInit", "CdlMute", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", + "CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, + NULL, "CdlTest", "CdlID", "CdlReadS", + "CdlReset", NULL, "CDlReadToc", NULL +}; + +u8 Test04[] = { 0 }; +u8 Test05[] = { 0 }; +u8 Test20[] = { 0x98, 0x06, 0x10, 0xC3 }; +u8 Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F }; +u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; + +// 1x = 75 sectors per second +// PSXCLK = 1 sec in the ps +// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz) +//#define cdReadTime ((PSXCLK / 75) / BIAS) +unsigned long cdReadTime;// = ((PSXCLK / 75) / BIAS); + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +/*static struct CdrStat stat; +static struct SubQ *subq;*/ + +#define CDR_INT(eCycle) PSX_INT(17, eCycle) +#define CDREAD_INT(eCycle) PSX_INT(18, eCycle) + +#define StartReading(type) { \ + cdr.Reading = type; \ + cdr.FirstSector = 1; \ + cdr.Readed = 0xff; \ + AddIrqQueue(READ_ACK, 0x800); \ +} + +#define StopReading() { \ + if (cdr.Reading) { \ + cdr.Reading = 0; \ + psxRegs.interrupt&=~0x40000; \ + } \ +} + +#define StopCdda() { \ + if (cdr.Play) { \ +/* if (!Config.Cdda) CDR_stop();*/ \ + cdr.StatP&=~0x80; \ + cdr.Play = 0; \ + } \ +} + +#define SetResultSize(size) { \ + cdr.ResultP = 0; \ + cdr.ResultC = size; \ + cdr.ResultReady = 1; \ +} + +s32 MSFtoLSN(u8 *Time) { + u32 lsn; + + lsn = Time[2]; + lsn+=(Time[1] - 2) * 75; + lsn+= Time[0] * 75 * 60; + return lsn; +} + +void LSNtoMSF(u8 *Time, s32 lsn) { + lsn += 150; + Time[2] = lsn / 4500; // minuten + lsn = lsn - Time[2] * 4500; // minuten rest + Time[1] = lsn / 75; // sekunden + Time[0] = lsn - Time[1] * 75; // sekunden rest +} + +void ReadTrack() { + cdr.Prev[0] = itob(cdr.SetSector[0]); + cdr.Prev[1] = itob(cdr.SetSector[1]); + cdr.Prev[2] = itob(cdr.SetSector[2]); + +#ifdef CDR_LOG + CDR_LOG("KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); +#endif + cdr.RErr = CDVDreadTrack(MSFtoLSN(cdr.SetSector), CDVD_MODE_2352); +} + +// cdr.Stat: +#define NoIntr 0 +#define DataReady 1 +#define Complete 2 +#define Acknowledge 3 +#define DataEnd 4 +#define DiskError 5 + +void AddIrqQueue(u8 irq, unsigned long ecycle) { + cdr.Irq = irq; + if (cdr.Stat) { + cdr.eCycle = ecycle; + } else { + CDR_INT(ecycle); + } +} + +int cdrInterrupt() { + cdvdTD trackInfo; + int i; + u8 Irq = cdr.Irq; + + if (cdr.Stat) { + CDR_INT(0x800); + return 0; + } + + cdr.Irq = 0xff; + cdr.Ctrl&=~0x80; + + switch (Irq) { + case CdlSync: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlNop: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +/* i = stat.Status; + if (CDR_getStatus(&stat) != -1) { + if (stat.Type == 0xff) cdr.Stat = DiskError; + if (stat.Status & 0x10) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x11; + cdr.Result[0]&=~0x02; + } + else if (i & 0x10) { + cdr.StatP |= 0x2; + cdr.Result[0]|= 0x2; + CheckCdrom(); + } + }*/ + break; + + case CdlSetloc: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlPlay: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + cdr.StatP|= 0x82; +// if ((cdr.Mode & 0x5) == 0x5) AddIrqQueue(REPPLAY, cdReadTime); + break; + + case CdlForward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlBackward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStandby: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStop: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP&=~0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; +// cdr.Stat = Acknowledge; + break; + + case CdlPause: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlPause + 0x20, 0x800); + break; + + case CdlPause + 0x20: + SetResultSize(1); + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlInit: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +// if (!cdr.Init) { + AddIrqQueue(CdlInit + 0x20, 0x800); +// } + break; + + case CdlInit + 0x20: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + cdr.Init = 1; + break; + + case CdlMute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlDemute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetfilter: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetmode: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlGetmode: + SetResultSize(6); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = cdr.Mode; + cdr.Result[2] = cdr.File; + cdr.Result[3] = cdr.Channel; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocL: + SetResultSize(8); +// for (i=0; i<8; i++) cdr.Result[i] = itob(cdr.Transfer[i]); + for (i=0; i<8; i++) cdr.Result[i] = cdr.Transfer[i]; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocP: + SetResultSize(8); +/* subq = (struct SubQ*) CDR_getBufferSub(); + if (subq != NULL) { + cdr.Result[0] = subq->TrackNumber; + cdr.Result[1] = subq->IndexNumber; + memcpy(cdr.Result+2, subq->TrackRelativeAddress, 3); + memcpy(cdr.Result+5, subq->AbsoluteAddress, 3); + } else { +*/ cdr.Result[0] = 1; + cdr.Result[1] = 1; + cdr.Result[2] = cdr.Prev[0]; + cdr.Result[3] = itob((btoi(cdr.Prev[1])) - 2); + cdr.Result[4] = cdr.Prev[2]; + memcpy(cdr.Result+5, cdr.Prev, 3); +// } + cdr.Stat = Acknowledge; + break; + + case CdlGetTN: + cdr.CmdProcess = 0; + SetResultSize(3); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + if (CDVDgetTN(&cdr.ResultTN) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + cdr.Stat = Acknowledge; + cdr.Result[1] = itob(cdr.ResultTN.strack); + cdr.Result[2] = itob(cdr.ResultTN.etrack); + } + break; + + case CdlGetTD: + cdr.CmdProcess = 0; + cdr.Track = btoi(cdr.Param[0]); + SetResultSize(4); + cdr.StatP|= 0x2; + if (CDVDgetTD(cdr.Track, &trackInfo) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + LSNtoMSF(cdr.ResultTD, trackInfo.lsn); + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = itob(cdr.ResultTD[0]); + cdr.Result[2] = itob(cdr.ResultTD[1]); + cdr.Result[3] = itob(cdr.ResultTD[2]); + } + break; + + case CdlSeekL: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekL + 0x20, 0x800); + break; + + case CdlSeekL + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlSeekP: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekP + 0x20, 0x800); + break; + + case CdlSeekP + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlTest: + cdr.Stat = Acknowledge; + switch (cdr.Param[0]) { + case 0x20: // System Controller ROM Version + SetResultSize(4); + memcpy(cdr.Result, Test20, 4); + break; + case 0x22: + SetResultSize(8); + memcpy(cdr.Result, Test22, 4); + break; + case 0x23: case 0x24: + SetResultSize(8); + memcpy(cdr.Result, Test23, 4); + break; + } + break; + + case CdlID: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlID + 0x20, 0x800); + break; + + case CdlID + 0x20: + SetResultSize(8); +// if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player + cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD +/* } + else { + if (stat.Type == 2) { + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x10; + } + else { + cdr.Result[0] = 0x00; + cdr.Result[1] = 0x00; + } + }*/ + if (!LoadCdBios) cdr.Result[1] |= 0x80; + + cdr.Result[2] = 0x00; + cdr.Result[3] = 0x00; + strncpy((char *)&cdr.Result[4], "PCSX", 4); + cdr.Stat = Complete; + break; + + case CdlReset: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlReadToc: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadToc + 0x20, 0x800); + break; + + case CdlReadToc + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case AUTOPAUSE: + cdr.OCUP = 0; +/* SetResultSize(1); + StopCdda(); + StopReading(); + cdr.OCUP = 0; + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = DataEnd; +*/ AddIrqQueue(CdlPause, 0x400); + break; + + case READ_ACK: + if (!cdr.Reading) return 1; + + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + ReadTrack(); + + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + + break; + + case REPPLAY_ACK: + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + SetResultSize(1); + AddIrqQueue(REPPLAY, cdReadTime); + break; + + case REPPLAY: + if ((cdr.Mode & 5) != 5) break; +/* if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Result[6] = 0; + cdr.Result[7] = 0; + } else memcpy(cdr.Result, &stat.Track, 8); + cdr.Stat = 1; + SetResultSize(8); + AddIrqQueue(REPPLAY_ACK, cdReadTime); +*/ break; + + case 0xff: + return 1; + + default: + cdr.Stat = Complete; + break; + } + + if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) psxHu32(0x1070)|=0x4; + +#ifdef CDR_LOG + CDR_LOG("Cdr Interrupt %x\n", Irq); +#endif + return 1; +} + +int cdrReadInterrupt() { + u8 *buf; + + if (!cdr.Reading) return 1; + + if (cdr.Stat) { + CDREAD_INT(0x800); + return 0; + } + +#ifdef CDR_LOG + CDR_LOG("KEY END"); +#endif + + cdr.OCUP = 1; + SetResultSize(1); + cdr.StatP|= 0x22; + cdr.Result[0] = cdr.StatP; + + SysMessage("Reading From CDR"); + buf = CDVDgetBuffer(); + if (buf == NULL) cdr.RErr = -1; + + if (cdr.RErr == -1) { +#ifdef CDR_LOG + fprintf(emuLog, " err\n"); +#endif + memset(cdr.Transfer, 0, 2340); + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + return 0; + } + + memcpy(cdr.Transfer, buf+12, 2340); + cdr.Stat = DataReady; + +#ifdef CDR_LOG + fprintf(emuLog, " %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); +#endif + +/* if ((cdr.Muted == 1) && (cdr.Mode & 0x40) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA + if ((cdr.Transfer[4+2] & 0x4) && + ((cdr.Mode&0x8) ? (cdr.Transfer[4+1] == cdr.Channel) : 1) && + (cdr.Transfer[4+0] == cdr.File)) { + int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); + + if (!ret) { + SPU_playADPCMchannel(&cdr.Xa); + cdr.FirstSector = 0; + } + else cdr.FirstSector = -1; + } + }*/ + + cdr.SetSector[2]++; + if (cdr.SetSector[2] == 75) { + cdr.SetSector[2] = 0; + cdr.SetSector[1]++; + if (cdr.SetSector[1] == 60) { + cdr.SetSector[1] = 0; + cdr.SetSector[0]++; + } + } + + cdr.Readed = 0; + + if ((cdr.Transfer[4+2] & 0x80) && (cdr.Mode & 0x2)) { // EOF +#ifdef CDR_LOG + CDR_LOG("AutoPausing Read\n"); +#endif +// AddIrqQueue(AUTOPAUSE, 0x800); + AddIrqQueue(CdlPause, 0x800); + } + else { + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + } + + psxHu32(0x1070)|=0x4; + return 0; +} + +/* +cdrRead0: + bit 0 - 0 REG1 command send / 1 REG1 data read + bit 1 - 0 data transfer finish / 1 data transfer ready/in progress + bit 2 - unknown + bit 3 - unknown + bit 4 - unknown + bit 5 - 1 result ready + bit 6 - 1 dma ready + bit 7 - 1 command being processed +*/ + +u8 cdrRead0(void) { + if (cdr.ResultReady) cdr.Ctrl|= 0x20; + else cdr.Ctrl&=~0x20; + + if (cdr.OCUP) cdr.Ctrl|= 0x40; + else cdr.Ctrl&=~0x40; + + // what means the 0x10 and the 0x08 bits? i only saw it used by the bios + cdr.Ctrl|=0x18; + +#ifdef CDR_LOG + CDR_LOG("CD0 Read: %x\n", cdr.Ctrl); +#endif + return psxHu8(0x1800) = cdr.Ctrl; +} + +/* +cdrWrite0: + 0 - to send a command / 1 - to get the result +*/ + +void cdrWrite0(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD0 write: %x\n", rt); +#endif + cdr.Ctrl = rt | (cdr.Ctrl & ~0x3); + + if (rt == 0) { + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + } +} + +u8 cdrRead1(void) { + if (cdr.ResultReady && cdr.Ctrl & 0x1) { + psxHu8(0x1801) = cdr.Result[cdr.ResultP++]; + if (cdr.ResultP == cdr.ResultC) cdr.ResultReady = 0; + } else psxHu8(0x1801) = 0; +#ifdef CDR_LOG + CDR_LOG("CD1 Read: %x\n", psxHu8(0x1801)); +#endif + return psxHu8(0x1801); +} + +void cdrWrite1(u8 rt) { + int i; + +#ifdef CDR_LOG + CDR_LOG("CD1 write: %x (%s)\n", rt, CmdName[rt]); +#endif +// psxHu8(0x1801) = rt; + cdr.Cmd = rt; + cdr.OCUP = 0; + +#ifdef CDRCMD_DEBUG + SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); + if (cdr.ParamC) { + SysPrintf(" Param[%d] = {", cdr.ParamC); + for (i=0;i cdr.ResultTN[1]) cdr.CurTrack = cdr.ResultTN[1]; + if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) { + int tmp = cdr.ResultTD[2]; + cdr.ResultTD[2] = cdr.ResultTD[0]; + cdr.ResultTD[0] = tmp; + if (!Config.Cdda) CDR_play(cdr.ResultTD); + } + } + } + else if (!Config.Cdda) CDR_play(cdr.SetSector); +*/ cdr.Play = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlForward: + if (cdr.CurTrack < 0xaa) cdr.CurTrack++; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlBackward: + if (cdr.CurTrack > 1) cdr.CurTrack--; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadN: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(1); + break; + + case CdlStandby: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlStop: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPause: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x40000); + break; + + case CdlReset: + case CdlInit: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlMute: + cdr.Muted = 0; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlDemute: + cdr.Muted = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetfilter: + cdr.File = cdr.Param[0]; + cdr.Channel = cdr.Param[1]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetmode: +#ifdef CDR_LOG + CDR_LOG("Setmode %x\n", cdr.Param[0]); +#endif + cdr.Mode = cdr.Param[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetmode: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocL: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocP: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTN: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTD: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekL: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekP: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlTest: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlID: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadS: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(2); + break; + + case CdlReadToc: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd); +#endif + return; + } + if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4; +} + +u8 cdrRead2(void) { + u8 ret; + + if (cdr.Readed == 0) { + ret = 0; + } else { + ret = *cdr.pTransfer++; + } + +#ifdef CDR_LOG + CDR_LOG("CD2 Read: %x\n", ret); +#endif + return ret; +} + +void cdrWrite2(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD2 write: %x\n", rt); +#endif + if (cdr.Ctrl & 0x1) { + switch (rt) { + case 0x07: + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + cdr.Ctrl = 0; + break; + + default: + cdr.Reg2 = rt; + break; + } + } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) { + cdr.Param[cdr.ParamP++] = rt; + cdr.ParamC++; + } +} + +u8 cdrRead3(void) { + if (cdr.Stat) { + if (cdr.Ctrl & 0x1) psxHu8(0x1803) = cdr.Stat | 0xE0; + else psxHu8(0x1803) = 0xff; + } else psxHu8(0x1803) = 0; +#ifdef CDR_LOG + CDR_LOG("CD3 Read: %x\n", psxHu8(0x1803)); +#endif + return psxHu8(0x1803); +} + +void cdrWrite3(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD3 write: %x\n", rt); +#endif + if (rt == 0x07 && cdr.Ctrl & 0x1) { + cdr.Stat = 0; + + if (cdr.Irq == 0xff) { cdr.Irq = 0; return; } + if (cdr.Irq) { + CDR_INT(cdr.eCycle); + }/* else if (cdr.Reading) { + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + }*/ + return; + } + if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { + cdr.Readed = 1; + cdr.pTransfer = cdr.Transfer; + + switch (cdr.Mode&0x30) { + case 0x10: + case 0x00: cdr.pTransfer+=12; break; + default: break; + } + } +} + +void psxDma3(u32 madr, u32 bcr, u32 chcr) { + u32 cdsize; + +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + switch (chcr) { + case 0x11000000: + case 0x11400100: + if (cdr.Readed == 0) { +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** NOT READY\n"); +#endif + return; + } + + cdsize = (bcr & 0xffff) * 4; + + memcpy((u8*)PSXM(madr), cdr.pTransfer, cdsize); + psxCpu->Clear(madr, cdsize/4); + cdr.pTransfer+=cdsize; + + break; + case 0x41000200: + //SysPrintf("unhandled cdrom dma3: madr: %x, bcr: %x, chcr %x\n", madr, bcr, chcr); + // size = 16 * 32 * 4 (one sector) +/* PSXMu8(madr+0) = 0x10; + PSXMu8(madr+1) = 0x00; + PSXMu8(madr+2) = 0x03; + PSXMu8(madr+3) = 0x00;*/ + return; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown cddma %lx\n", chcr); +#endif + break; + } + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); +} + +void cdrReset() { + memset(&cdr, 0, sizeof(cdr)); + cdr.CurTrack=1; + cdr.File=1; cdr.Channel=1; + cdReadTime = (PSXCLK / 1757) * BIAS; + //DVD is 4x (PSXCLK / 75) CD is 24x on the PS2, so that would mean CD = (PSXCLK / 450) + // 75/4 = 18.75 x 24 = 450 remember its faster than the PS1 ;) Refraction + + // with the timing set to 60 Gran Turismo works + // anybody knows why it doesn't with 75? + // 75 is the correct cdrom timing +// if (Config.CdTiming) +// cdReadTime = (PSXCLK / 60) / BIAS; + // this seems to be the most compatible + // let's leave like this until we know why + // 75 is buggy with some games +} + +int cdrFreeze(gzFile f, int Mode) { + int tmp; + + gzfreeze(&cdr, sizeof(cdr)); + + if (Mode == 1) tmp = cdr.pTransfer - cdr.Transfer; + gzfreezel(&tmp); + if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp; + + return 0; +} + diff --git a/CdRom.h b/CdRom.h new file mode 100644 index 0000000000..569909e20b --- /dev/null +++ b/CdRom.h @@ -0,0 +1,92 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDROM_H__ +#define __CDROM_H__ + +#include "PsxCommon.h" +#include "Decode_XA.h" +#include "PS2Edefs.h" + +typedef struct { + u8 OCUP; + u8 Reg1Mode; + u8 Reg2; + u8 CmdProcess; + u8 Ctrl; + u8 Stat; + + u8 StatP; + + u8 Transfer[2352]; + u8 *pTransfer; + + u8 Prev[4]; + u8 Param[8]; + u8 Result[8]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + u8 ResultReady; + u8 Cmd; + u8 Readed; + unsigned long Reading; + + cdvdTN ResultTN; + u8 ResultTD[4]; + u8 SetSector[4]; + u8 SetSectorSeek[4]; + u8 Track; + int Play; + int CurTrack; + int Mode, File, Channel, Muted; + int Reset; + int RErr; + int FirstSector; + + xa_decode_t Xa; + + int Init; + + u8 Irq; + unsigned long eCycle; + + char Unused[4087]; +} cdrStruct; + +cdrStruct cdr; + +s32 MSFtoLSN(u8 *Time); +void LSNtoMSF(u8 *Time, s32 lsn); + +void cdrReset(); +int cdrInterrupt(); +int cdrReadInterrupt(); +u8 cdrRead0(void); +u8 cdrRead1(void); +u8 cdrRead2(void); +u8 cdrRead3(void); +void cdrWrite0(u8 rt); +void cdrWrite1(u8 rt); +void cdrWrite2(u8 rt); +void cdrWrite3(u8 rt); +int cdrFreeze(gzFile f, int Mode); + +#endif /* __CDROM_H__ */ diff --git a/Common.h b/Common.h new file mode 100644 index 0000000000..f4d674a618 --- /dev/null +++ b/Common.h @@ -0,0 +1,260 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include +#if defined(__WIN32__) + +#include + +typedef struct { + HWND hWnd; // Main window handle + HINSTANCE hInstance; // Application instance + HMENU hMenu; // Main window menu + HANDLE hConsole; +} AppData; + +extern AppData gApp; +#define pthread_mutex__unlock pthread_mutex_unlock + +#elif defined (__LINUX__) + +#include +#include // posix_memalign() +#define BOOL int + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +#define strnicmp strncasecmp +#define stricmp strcasecmp + +// Definitions added Feb 16, 2006 by efp +#define __declspec(x) +#define __forceinline inline +#define _aligned_malloc(x,y) posix_memalign(y,x) +#define _aligned_free(x) free(x) +#define pthread_mutex__unlock pthread_mutex_unlock + +#endif + +#if defined(__MINGW32__) +#include +#include +#define BOOL int +#include // posix_memalign() +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +//#define max(a,b) (((a) > (b)) ? (a) : (b)) +//#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define __declspec(x) +#define __assume(x) ; +#define strnicmp strncasecmp +#define stricmp strcasecmp +#include +//#pragma intrinsic (InterlockedAnd) +// Definitions added Feb 16, 2006 by efp +//#define __declspec(x) +#include +#define __forceinline inline +#define _aligned_malloc(x,y) __mingw_aligned_malloc(x,y) +#define _aligned_free(x) __mingw_aligned_free(x) +#define pthread_mutex__unlock pthread_mutex_unlock + +#define fpusqrtf sqrtf +#define fpufabsf fabsf +#define fpusinf sinf +#define fpucosf cosf +#define fpuexpf expf +#define fpuatanf atanf +#define fpuatan2f atan2f + +#endif +#ifdef ENABLE_NLS + +#ifdef __MSCW32__ +#include "libintlmsc.h" +#else +#include "libintl.h" +#endif + +#undef _ +#define _(String) dgettext (PACKAGE, String) +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +# define N_(String) (String) +#endif + +#else + +#define _(msgid) msgid +#define N_(msgid) msgid + +#endif + +#include "PS2Etypes.h" + +#ifdef PCSX2_DEVBUILD + +typedef struct _TESTRUNARGS +{ + u8 enabled; + u8 jpgcapture; + int frame; // if < 0, frame is unlimited (run until crash). + int numimages; + int curimage; + u32 autopad; // mask for auto buttons + int efile; + int snapdone; + + char* ptitle; + char* pimagename; + char* plogname; + char* pgsdll, *pcdvddll, *pspudll; + +} TESTRUNARGS; + +extern TESTRUNARGS g_TestRun; + +#endif + +#define BIAS 2 // Bus is half of the actual ps2 speed +//#define PS2CLK 36864000 /* 294.912 mhz */ +//#define PSXCLK 9216000 /* 36.864 Mhz */ +//#define PSXCLK 186864000 /* 36.864 Mhz */ +#define PS2CLK 294912000 /* 294.912 mhz */ +#define PSXCLK 36864000 /* 36.864 Mhz */ + + +/* Config.PsxType == 1: PAL: + VBlank interlaced 50.00 Hz + VBlank non-interlaced 49.76 Hz + HBlank 15.625 KHz + Config.PsxType == 0: NSTC + VBlank interlaced 59.94 Hz + VBlank non-interlaced 59.82 Hz + HBlank 15.73426573 KHz */ +#define PS2VBLANK_NTSC_INT ((int)(PS2CLK / 59.94)) +#define PS2VBLANK_NTSC ((int)(PS2CLK / 59.82)) +#define PS2VBLANK_PAL_INT ((int)(PS2CLK / 50.00)) +#define PS2VBLANK_PAL ((int)(PS2CLK / 49.76)) +#define VBLANK_NTSC ((Config.PsxType & 2) ? 59.94 : 59.82) +#define VBLANK_PAL ((Config.PsxType & 2) ? 50.00 : 49.76) +#define HBLANK_NTSC (15734.26573) +#define HBLANK_PAL (15625) + +#define PS2HBLANK_NTSC ((int)(PS2CLK / HBLANK_NTSC)) +#define PS2HBLANK_PAL ((int)(PS2CLK / HBLANK_PAL)) +#define PS2HBLANK ((int)((Config.PsxType & 1) ? PS2HBLANK_PAL : PS2HBLANK_NTSC)) +#define PSXVBLANK_NTSC ((int)(PSXCLK / VBLANK_NTSC)) +#define PSXVBLANK_PAL ((int)(PSXCLK / VBLANK_PAL)) +#define PSXVBLANK ((int)((Config.PsxType & 1) ? PSXVBLANK_PAL : PSXVBLANK_NTSC)) +#define PSXHBLANK_NTSC ((int)(PSXCLK / HBLANK_NTSC)) +#define PSXHBLANK_PAL ((int)(PSXCLK / HBLANK_PAL)) +#define PSXHBLANK ((int)((Config.PsxType & 1) ? PSXHBLANK_PAL : PSXHBLANK_NTSC)) +#define PSXPIXEL ((int)(PSXCLK / 13500000)) +#define PSXSOUNDCLK ((int)(48000)) + +#define COLOR_BLACK "\033[30m" +#define COLOR_RED "\033[31m" +#define COLOR_GREEN "\033[32m" +#define COLOR_YELLOW "\033[33m" +#define COLOR_BLUE "\033[34m" +#define COLOR_MAGENTA "\033[35m" +#define COLOR_CYAN "\033[36m" +#define COLOR_WHITE "\033[37m" +#define COLOR_RESET "\033[0m" + +#include // sync functions + +#include "R5900.h" +#include "Debug.h" +#include "System.h" +#include "Memory.h" +#include "Elfheader.h" +#include "Hw.h" +#include "GS.h" +#include "Vif.h" +#include "SPR.h" +#include "Sif.h" +#include "Plugins.h" +#include "PS2Edefs.h" +#include "Counters.h" +#include "IPU.h" +#include "Misc.h" +#include "Patch.h" +#include "Stats.h" +#include "COP0.h" +#include "VifDma.h" +#if (defined(__i386__) || defined(__x86_64__)) +#include "ix86/ix86.h" +#endif + +#define gzfreeze(ptr, size) \ + if (Mode == 1) gzwrite(f, ptr, size); \ + else if (Mode == 0) gzread(f, ptr, size); + +#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr)) + +int cdCaseopen; + +extern void __Log(char *fmt, ...); +extern u16 logProtocol; +extern u8 logSource; +#define PCSX2_VERSION "0.9.1" + +#ifdef __MSCW32__ +// C++ code for sqrtf +void InitFPUOps(); +extern float (*fpusqrtf)(float fval); +extern float (*fpufabsf)(float fval); +extern float (*fpusinf)(float fval); +extern float (*fpucosf)(float fval); +extern float (*fpuexpf)(float fval); +extern float (*fpuatanf)(float fval); +extern float (*fpuatan2f)(float fvalx, float fvaly); +#endif +// Added Feb 16, 2006 by efp +#ifdef __LINUX__ +#include // EBUSY +#endif /* __LINUX__ */ + +#define DESTROY_MUTEX(mutex) { \ + int err = pthread_mutex_destroy(&mutex); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#mutex"\n"); \ +} \ + +#define DESTROY_COND(cond) { \ + int err = pthread_cond_destroy(&cond); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#cond"\n"); \ +} \ + +#endif /* __COMMON_H__ */ diff --git a/Counters.c b/Counters.c new file mode 100644 index 0000000000..36fad2f221 --- /dev/null +++ b/Counters.c @@ -0,0 +1,493 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "PsxCommon.h" + +int gates = 0; +u8 eehblankgate = 0; +int cnts = 5; +extern u8 psxhblankgate; +int hblankend = 1; +Counter counters[6]; +u32 nextCounter, nextsCounter; + +void rcntUpdTarget(int index) { + counters[index].sCycleT = cpuRegs.cycle; + counters[index].CycleT = (counters[index].target - rcntRcount(index)) * counters[index].rate; +} + +void rcntUpd(int index) { + counters[index].sCycle = cpuRegs.cycle; + counters[index].Cycle = (0xffff - (rcntRcount(index)&0xffff)) * counters[index].rate; + rcntUpdTarget(index); +} + +void rcntReset(int index) { + counters[index].count = 0; + counters[index].mode&= ~0x00400C00; + rcntUpd(index); +} + +void rcntSet() { + u32 c; + int i; + + nextCounter = 0xffff; + nextsCounter = cpuRegs.cycle; + + for (i = 0; i < 4; i++) { + if ((counters[i].mode & 0x380) < 0x80) continue; // Stopped + + if (counters[i].mode & 0x200){ + c = (0xffff - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + } + if ((counters[i].mode & 0x500) == 0x100){ + c = (counters[i].target - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + } + } + //Calculate HBlank + c = counters[4].CycleT - (cpuRegs.cycle - counters[4].sCycleT); + if (c < nextCounter) { + nextCounter = c; + } + c = counters[5].CycleT - (cpuRegs.cycle - counters[5].sCycleT); + if (c < nextCounter) { + nextCounter = c; + } +} + +void rcntInit() { + int i; + + memset(counters, 0, sizeof(counters)); + + for (i=0; i<4; i++) { + counters[i].rate = 2; + counters[i].target = 0xffff; + } + counters[0].interrupt = 9; + counters[1].interrupt = 10; + counters[2].interrupt = 11; + counters[3].interrupt = 12; + + counters[4].mode = 0x3c0; // The VSync counter mode + //counters[4].count = 0; + counters[5].mode = 0x3c0; + UpdateVSyncRate(); + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + counters[4].CycleT = counters[4].rate; + counters[4].Cycle = counters[4].rate; + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + counters[5].CycleT = counters[5].rate; + counters[5].Cycle = counters[5].rate; + for (i=0; i<4; i++) rcntUpd(i); + rcntSet(); +} + +void UpdateVSyncRate() { + if (Config.PsxType & 1) { + counters[4].rate = PS2HBLANK_PAL; + if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_PAL_INT; + else counters[5].rate = PS2VBLANK_PAL; + } else { + counters[4].rate = PS2HBLANK_NTSC; + if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_NTSC_INT; + else counters[5].rate = PS2VBLANK_NTSC; + } +} + + +#define NOSTATS + +// debug code, used for stats +int g_nCounters[4]; +extern u32 s_lastvsync[2]; +LARGE_INTEGER lfreq; +static int iFrame = 0; + +void FrameLimiter() +{ + static u32 dwStartTime = 0, dwEndTime = 0; + + // do over 4 frames instead of 1 + if( (iFrame&3) == 0 ) { + u32 frames = (Config.PsxType&1) ? (4000 / 50 -1) : (4000 / 60 - 1); + dwEndTime = timeGetTime(); + + if( dwEndTime < dwStartTime + frames ) { + Sleep(frames-(dwEndTime-dwStartTime)); + } + + dwStartTime = timeGetTime(); + } +} + +extern u32 CSRw; +extern u32 SuperVUGetRecTimes(int clear); +extern u32 vu0time; + +#include "VU.h" +void VSync() { + + //QueryPerformanceFrequency(&lfreq); + + if (counters[5].mode & 0x10000) { // VSync End (22 hsyncs) + + // swap the vsync field + u32 newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000; + *(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield; + iFrame++; + + // wait until GS stops + if( CHECK_MULTIGS ) { + GSRingBufVSync(newfield); + } + else { +#ifdef GSCAPTURE + extern u32 g_gstransnum; + g_gstransnum = 0; +#endif + GSvsync(newfield); + } + + //SysPrintf("c: %x, %x\n", cpuRegs.cycle, *(u32*)&VU1.Micro[16]); + //if( (iFrame%20) == 0 ) SysPrintf("svu time: %d\n", SuperVUGetRecTimes(1)); +// if( (iFrame%10) == 0 ) { +// SysPrintf("vu0 time: %d\n", vu0time); +// vu0time = 0; +// } + + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled && g_TestRun.frame > 0 ) { + if( iFrame > g_TestRun.frame ) { + // take a snapshot + if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) { + if( g_TestRun.snapdone ) { + g_TestRun.curimage++; + g_TestRun.snapdone = 0; + g_TestRun.frame += 20; + if( g_TestRun.curimage >= g_TestRun.numimages ) { + // exit + SysClose(); + exit(0); + } + } + else { + // query for the image + GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture); + } + } + else { + // exit + SysClose(); + exit(0); + } + } + } +#endif + + if( CHECK_FRAMELIMIT ) FrameLimiter(); + + counters[5].mode&= ~0x10000; + //UpdateVSyncRate(); + GSCSRr |= 8; // signal + if (CSRw & 0x8){ + CSRw &= ~8; + if (!(GSIMR&0x800) ) + gsIrq(); + } + hwIntcIrq(3); + psxVSyncEnd(); +#ifndef NOSTATS + statsVSync(); +#endif + if(gates)rcntEndGate(0x8); + SysUpdate(); + } else { // VSync Start (240 hsyncs) + //UpdateVSyncRateEnd(); + + //SysPrintf("ctrs: %d %d %d %d\n", g_nCounters[0], g_nCounters[1], g_nCounters[2], g_nCounters[3]); + //SysPrintf("vif: %d\n", (((LARGE_INTEGER*)g_nCounters)->QuadPart * 1000000) / lfreq.QuadPart); + //memset(g_nCounters, 0, 16); + counters[5].mode|= 0x10000; + //GSCSRr|= 0x8; + hwIntcIrq(2); + psxVSyncStart(); + + if(Config.Patch) applypatch(1); + if(gates)rcntStartGate(0x8); + +// __Log("%u %u 0\n", cpuRegs.cycle-s_lastvsync[1], timeGetTime()-s_lastvsync[0]); +// s_lastvsync[0] = timeGetTime(); +// s_lastvsync[1] = cpuRegs.cycle; + } +} + + + +void rcntUpdate() { + int i; + + for (i=0; i<=3; i++) { + if ((counters[i].mode & 0x380) < 0x80) continue; // Stopped + + + + if (rcntCycle(i) >= counters[i].target) { // Target interrupt + if ((counters[i].mode & 0x500) == 0x100) { // 0x400 == 0 so target interrupt hasnt happened + counters[i].mode|= 0x0400; // Target flag + //counters[i].mode&= ~0x800; + + hwIntcIrq(counters[i].interrupt); +// SysPrintf("counter[%d] target interrupt (%x)\n", i, cpuRegs.cycle); + } + if (counters[i].mode & 0x40) { // Reset on target + counters[i].count = 0; + rcntUpd(i); + } + } + + + + if (rcntCycle(i) >= 0xffff) { + if (counters[i].mode & 0x0200) { // Overflow interrupt + counters[i].mode|= 0x0800; // Overflow flag + hwIntcIrq(counters[i].interrupt); +// SysPrintf("counter[%d] overflow interrupt (%x)\n", i, cpuRegs.cycle); + } + counters[i].count = 0; + rcntUpd(i); + } + + } + + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT / 2 && hblankend == 0){ + GSCSRr |= 4; // signal + if (CSRw & 0x4){ + CSRw &= ~4; + if (!(GSIMR&0x400) ) + gsIrq(); + } + if(eehblankgate)rcntEndGate(0); + if(psxhblankgate)psxCheckEndGate(0); + hblankend = 1; + } + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT) { + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + counters[4].CycleT = counters[4].rate; + counters[4].Cycle = counters[4].rate; + + + if(gates)rcntStartGate(0); + psxCheckStartGate(0); + hblankend = 0; + } + + if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT / 2 && (counters[5].mode & 0x10000)) VSync(); + + if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) { + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + counters[5].CycleT = counters[5].rate; + counters[5].Cycle = counters[5].rate; + VSync(); + } + rcntSet(); +} + +void rcntWcount(int index, u32 value) { + //SysPrintf ("writeCcount[%d] = %x\n", index, value); +#ifdef PSXCNT_LOG + PSXCNT_LOG("EE count write %d count %x eecycle %x\n", index, counters[index].count, cpuRegs.eCycle); +#endif + + //counters[index].mode &= ~0x00400C00; + counters[index].count = value; + rcntUpd(index); + rcntSet(); +} + +void rcntWmode(int index, u32 value) { +// SysPrintf ("writeCmode[%ld] = %lx\n", index, value); +#ifdef PSXCNT_LOG + PSXCNT_LOG("EE counter set %d mode %x\n", index, counters[index].mode); +#endif + if (value & 0xc00) { + counters[index].mode &= ~(value & 0xc00); + } + /*if ((counters[index].mode & 0x37F) == (value & 0x37f)){ //Stop Counting + if((counters[index].mode & 0x80) != (value & 0x80)){ + SysPrintf("EE Counter %x %s\n", index, (counters[index].mode & 0x80) ? "stopped" : "started"); + if(counters[index].mode & 0x80) counters[index].count = rcntRcount(index); + counters[index].mode ^= 0x80; + rcntUpd(index); + } + rcntSet(); + return; + }*/ + if(!(value & 0x80)){ + counters[index].count = rcntRcount(index); + rcntUpd(index); + } + +counters[index].mode = (value & 0x3ff) | (counters[index].mode & 0xc00); + + + switch (value & 0x3) { //Clock rate divisers *2, they use BUSCLK speed not PS2CLK + case 0: counters[index].rate = 2; break; + case 1: counters[index].rate = 32; break; + case 2: counters[index].rate = 512; break; + case 3: counters[index].rate = PS2HBLANK; break; + } + + if((counters[index].mode & 0xF) == 0x7) { + gates &= ~(1<> 4){ + case 0x0: //Count When Signal is low (off) + counters[i].count = rcntRcount(i); + //rcntUpd(i); + counters[i].mode &= ~0x80; + break; + case 0x1: //Reset and start counting on Vsync start + counters[i].mode |= 0x80; + rcntReset(i); + break; + case 0x2: //Reset and start counting on Vsync end + //Do Nothing + break; + case 0x3: //Reset and start counting on Vsync start and end + counters[i].mode |= 0x80; + rcntReset(i); + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntEndGate(int mode){ + int i; + + for(i=0; i <=3; i++){ //Gates for counters + if(!(gates & (1<> 4){ + case 0x0: //Count When Signal is low (off) + rcntUpd(i); + counters[i].mode |= 0x80; + break; + case 0x1: //Reset and start counting on Vsync start + //Do Nothing + break; + case 0x2: //Reset and start counting on Vsync end + rcntReset(i); + counters[i].mode |= 0x80; + break; + case 0x3: //Reset and start counting on Vsync start and end + rcntReset(i); + counters[i].mode |= 0x80; + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntWtarget(int index, u32 value) { + //SysPrintf ("writeCtarget[%ld] = %lx\n", index, value); +#ifdef PSXCNT_LOG + PSXCNT_LOG("EE target write %d target %x eecycle %x\n", index, counters[index].target, cpuRegs.eCycle); +#endif + counters[index].target = value; + //counters[index].mode &= ~0x00400400; + counters[index].CycleT = (counters[index].target - rcntRcount(index)) * counters[index].rate; + //rcntUpdTarget(index); + rcntSet(); +} + +void rcntWhold(int index, u32 value) { + //SysPrintf ("writeChold[%ld] = %lx\n", index, value); + counters[index].hold = value; + //rcntUpd(index); + //rcntSet(); +} + +u16 rcntRcount(int index) { + u16 ret; + if ((counters[index].mode & 0x80)) { + ret = counters[index].count + ((cpuRegs.cycle - counters[index].sCycle) / counters[index].rate); + }else{ + ret = counters[index].count; + } +// SysPrintf("rcntRcount[%d] %x\n", index, ret); + return (u16)ret; +} + +u32 rcntCycle(int index) { + + if ((counters[index].mode & 0x80)) { + return counters[index].count + ((cpuRegs.cycle - counters[index].sCycle) / counters[index].rate); + }else{ + return counters[index].count; + } +} + +int rcntFreeze(gzFile f, int Mode) { + gzfreezel(counters); + gzfreeze(&nextCounter, sizeof(nextCounter)); + gzfreeze(&nextsCounter, sizeof(nextsCounter)); + + return 0; +} + diff --git a/Counters.h b/Counters.h new file mode 100644 index 0000000000..8db0188b4b --- /dev/null +++ b/Counters.h @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COUNTERS_H__ +#define __COUNTERS_H__ + +typedef struct { + u32 count, mode, target, hold; + u32 rate, interrupt; + u32 Cycle, sCycle; + u32 CycleT, sCycleT; +} Counter; + +extern Counter counters[6]; +extern u32 nextCounter, nextsCounter; + +void rcntInit(); +void rcntUpdate(); +void rcntStartGate(int mode); +void rcntEndGate(int mode); +void rcntWcount(int index, u32 value); +void rcntWmode(int index, u32 value); +void rcntWtarget(int index, u32 value); +void rcntWhold(int index, u32 value); +u16 rcntRcount(int index); +u32 rcntCycle(int index); +int rcntFreeze(gzFile f, int Mode); + +void UpdateVSyncRate(); + +#endif /* __COUNTERS_H__ */ diff --git a/DebugTools/Debug.h b/DebugTools/Debug.h new file mode 100644 index 0000000000..d5975336d2 --- /dev/null +++ b/DebugTools/Debug.h @@ -0,0 +1,135 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include "Common.h" + +FILE *emuLog; + +char* disR5900F(u32 code, u32 pc); +char* disR5900Fasm(u32 code, u32 pc); +char* disR3000Fasm(u32 code, u32 pc); + +void disR5900AddSym(u32 addr, char *name); +char* disR5900GetSym(u32 addr); +char* disR5900GetUpperSym(u32 addr); +void disR5900FreeSyms(); + +char* disVU0MicroUF(u32 code, u32 pc); +char* disVU0MicroLF(u32 code, u32 pc); +char* disVU1MicroUF(u32 code, u32 pc); +char* disVU1MicroLF(u32 code, u32 pc); + +char* disR3000AF(u32 code, u32 pc); + +extern char *CP2VFnames[]; +extern char *disRNameCP2f[]; +extern char *disRNameCP2i[]; + +//that way is slower but you now not need to compile every time ;P +#ifdef PCSX2_DEVBUILD + +int Log; +u32 varLog; + +//memcars has the same number as PAD_LOG +#define MEMCARDS_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log + +#define CPU_LOG if (varLog & 0x00000001) {logProtocol=1; logSource='E';} if (varLog & 0x00000001) __Log +#define MEM_LOG if (varLog & 0x00000002) {logProtocol=6; logSource='E';} if (varLog & 0x00000002) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000002) __Log +#define HW_LOG if (varLog & 0x00000004) {logProtocol=6; logSource='E';} if (varLog & 0x00000004) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000004) __Log +#define DMA_LOG if (varLog & 0x00000008) {logProtocol=5; logSource='E';} if (varLog & 0x00000008) __Log +#define BIOS_LOG if (varLog & 0x00000010) {logProtocol=0; logSource='E';} if (varLog & 0x00000010) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000010) __Log +#define ELF_LOG if (varLog & 0x00000020) {logProtocol=7; logSource='E';} if (varLog & 0x00000020) __Log +#define FPU_LOG if (varLog & 0x00000040) {logProtocol=1; logSource='E';} if (varLog & 0x00000040) __Log +#define MMI_LOG if (varLog & 0x00000080) {logProtocol=1; logSource='E';} if (varLog & 0x00000080) __Log +#define VU0_LOG if (varLog & 0x00000100) {logProtocol=2; logSource='E';} if (varLog & 0x00000100) __Log +#define COP0_LOG if (varLog & 0x00000200) {logProtocol=1; logSource='E';} if (varLog & 0x00000200) __Log +#define VIF_LOG if (varLog & 0x00000400) {logProtocol=3; logSource='E';} if (varLog & 0x00000400) __Log +#define SPR_LOG if (varLog & 0x00000800) {logProtocol=7; logSource='E';} if (varLog & 0x00000800) __Log +#define GIF_LOG if (varLog & 0x00001000) {logProtocol=4; logSource='E';} if (varLog & 0x00001000) __Log +#define SIF_LOG if (varLog & 0x00002000) {logProtocol=9; logSource='E';} if (varLog & 0x00002000) __Log +#define IPU_LOG if (varLog & 0x00004000) {logProtocol=8; logSource='E';} if (varLog & 0x00004000) __Log +#define VUM_LOG if (varLog & 0x00008000) {logProtocol=2; logSource='E';} if (varLog & 0x00008000) __Log +#define RPC_LOG if (varLog & 0x00010000) {logProtocol=9; logSource='E';} if (varLog & 0x00010000) __Log + +#define PSXCPU_LOG if (varLog & 0x00100000) {logProtocol=1; logSource='I';} if (varLog & 0x00100000) __Log +#define PSXMEM_LOG if (varLog & 0x00200000) {logProtocol=6; logSource='I';} if (varLog & 0x00200000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00200000) __Log +#define PSXHW_LOG if (varLog & 0x00400000) {logProtocol=2; logSource='I';} if (varLog & 0x00400000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00400000) __Log +#define PSXBIOS_LOG if (varLog & 0x00800000) {logProtocol=0; logSource='I';} if (varLog & 0x00800000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00800000) __Log +#define PSXDMA_LOG if (varLog & 0x01000000) {logProtocol=5; logSource='I';} if (varLog & 0x01000000) __Log + +#define PAD_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log +#define GTE_LOG if (varLog & 0x04000000) {logProtocol=3; logSource='I';} if (varLog & 0x04000000) __Log +#define CDR_LOG if (varLog & 0x08000000) {logProtocol=8; logSource='I';} if (varLog & 0x08000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x08000000) __Log +#define GPU_LOG if (varLog & 0x10000000) {logProtocol=4; logSource='I';} if (varLog & 0x10000000) __Log +#define PSXCNT_LOG if (varLog & 0x20000000) {logProtocol=0; logSource='I';} if (varLog & 0x20000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x20000000) __Log + +#if defined (CPU_LOG) || defined(MEM_LOG) || defined(HW_LOG) || defined(DMA_LOG) || \ + defined(BIOS_LOG) || defined(ELF_LOG) || defined(FPU_LOG) || defined(MMI_LOG) || \ + defined(VU0_LOG) || defined(COP0_LOG) || defined(VIF_LOG) || defined(SPR_LOG) || \ + defined(GIF_LOG) || defined(SIF_LOG) || defined(IPU_LOG) || defined(VUM_log) || \ + defined(PSXCPU_LOG) || defined(PSXMEM_LOG)|| defined(IOPBIOS_LOG)|| defined(IOPHW_LOG)|| \ + defined(PAD_LOG) || defined(GTE_LOG) || defined(CDR_LOG) || defined(GPU_LOG) || \ + defined(MEMCARDS_LOG)|| defined(PSXCNT_LOG) +#define EMU_LOG __Log +#endif + +#else // PCSX2_DEVBUILD + +#define varLog 0 +#define Log 0 + +#define CPU_LOG 0&& +#define MEM_LOG 0&& +#define HW_LOG 0&& +#define DMA_LOG 0&& +#define BIOS_LOG 0&& +#define ELF_LOG 0&& +#define FPU_LOG 0&& +#define MMI_LOG 0&& +#define VU0_LOG 0&& +#define COP0_LOG 0&& +#define VIF_LOG 0&& +#define SPR_LOG 0&& +#define GIF_LOG 0&& +#define SIF_LOG 0&& +#define IPU_LOG 0&& +#define VUM_LOG 0&& +#define RPC_LOG 0&& + +#define PSXCPU_LOG 0&& +#define PSXMEM_LOG 0&& +#define PSXHW_LOG 0&& +#define PSXBIOS_LOG 0&& +#define PSXDMA_LOG 0&& + +#define PAD_LOG 0&& +#define GTE_LOG 0&& +#define CDR_LOG 0&& +#define GPU_LOG 0&& +#define PSXCNT_LOG 0&& + +#define EMU_LOG 0&& + +#endif + +#endif /* __DEBUG_H__ */ diff --git a/DebugTools/DisASM.h b/DebugTools/DisASM.h new file mode 100644 index 0000000000..ceb5917486 --- /dev/null +++ b/DebugTools/DisASM.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "R5900.h" + +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +///******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) + +//IOP + +#define DECODE_RD_IOP ((psxRegs.code >> 11) & 0x1F) +#define DECODE_RT_IOP ((psxRegs.code >> 16) & 0x1F) +#define DECODE_RS_IOP ((psxRegs.code >> 21) & 0x1F) +#define DECODE_IMMED_IOP ( psxRegs.code & 0xFFFF) +#define DECODE_SA_IOP ((psxRegs.code >> 6) & 0x1F) +#define DECODE_FS_IOP (DECODE_RD_IOP) + diff --git a/DebugTools/DisR3000A.c b/DebugTools/DisR3000A.c new file mode 100644 index 0000000000..d0dad71eb2 --- /dev/null +++ b/DebugTools/DisR3000A.c @@ -0,0 +1,318 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Debug.h" + +char ostr[256]; + +// Names of registers +static char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra"}; + +static char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , + "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; + + +// Type deffinition of our functions + +typedef char* (*TdisR3000AF)(u32 code, u32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisFg(fn, b) char* fn(u32 code, u32 pc) { b; return ostr; } +#define MakeDisF(fn, b) \ + static char* fn(u32 code, u32 pc) { \ + sprintf (ostr, "%8.8lx %8.8lx:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + + +#include "R3000A.h" + +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ +#undef _Target_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i]) +#define dCP0(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i]) +#define dHI() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.hi, "hi") +#define dLO() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.lo, "lo") +#define dImm() sprintf(ostr, "%s %4.4lx (%ld),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8lx,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2lx (%ld),", ostr, _Sa_, _Sa_) +#define dOfB() sprintf(ostr, "%s %4.4lx (%8.8lx (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8lx,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8lx,", ostr, (code >> 6) & 0xffffff) + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register arithmetic & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();) +MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();) +MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();) + +/********************************************************* +* Move from GPR to HI/LO * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +MakeDisF(disBREAK, dName("BREAK")) +MakeDisF(disRFE, dName("RFE")) +MakeDisF(disSYSCALL, dName("SYSCALL")) + + + +MakeDisF(disRTPS, dName("RTPS")) +MakeDisF(disOP , dName("OP")) +MakeDisF(disNCLIP, dName("NCLIP")) +MakeDisF(disDPCS, dName("DPCS")) +MakeDisF(disINTPL, dName("INTPL")) +MakeDisF(disMVMVA, dName("MVMVA")) +MakeDisF(disNCDS , dName("NCDS")) +MakeDisF(disCDP , dName("CDP")) +MakeDisF(disNCDT , dName("NCDT")) +MakeDisF(disNCCS , dName("NCCS")) +MakeDisF(disCC , dName("CC")) +MakeDisF(disNCS , dName("NCS")) +MakeDisF(disNCT , dName("NCT")) +MakeDisF(disSQR , dName("SQR")) +MakeDisF(disDCPL , dName("DCPL")) +MakeDisF(disDPCT , dName("DPCT")) +MakeDisF(disAVSZ3, dName("AVSZ3")) +MakeDisF(disAVSZ4, dName("AVSZ4")) +MakeDisF(disRTPT , dName("RTPT")) +MakeDisF(disGPF , dName("GPF")) +MakeDisF(disGPL , dName("GPL")) +MakeDisF(disNCCT , dName("NCCT")) + +MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);) +MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);) +MakeDisF(disMTC2, dName("MTC2")) +MakeDisF(disCTC2, dName("CTC2")) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget();) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR(_Rs_);) +MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_)) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);) +MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disNULL , disNULL, disNULL, disNULL , disNULL }; + +MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) diff --git a/DebugTools/DisR3000asm.c b/DebugTools/DisR3000asm.c new file mode 100644 index 0000000000..d2e0612268 --- /dev/null +++ b/DebugTools/DisR3000asm.c @@ -0,0 +1,361 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "R3000A.h" +#include "DisASM.h" + +unsigned long IOP_opcode_addr; + +char *GPR_IOP_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_IOP_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +void IOPD_SPECIAL(char *buf); +void IOPD_REGIMM(char *buf); +void IOPD_J(char *buf); +void IOPD_JAL(char *buf); +void IOPD_BEQ(char *buf); +void IOPD_BNE(char *buf); +void IOPD_BLEZ(char *buf); +void IOPD_BGTZ(char *buf); +void IOPD_ADDI(char *buf); +void IOPD_ADDIU(char *buf); +void IOPD_SLTI(char *buf); +void IOPD_SLTIU(char *buf); +void IOPD_ANDI(char *buf); +void IOPD_ORI(char *buf); +void IOPD_XORI(char *buf); +void IOPD_LUI(char *buf); +void IOPD_COP0(char *buf); +void IOPD_COP2(char *buf); +void IOPD_LB(char *buf); +void IOPD_LH(char *buf); +void IOPD_LWL(char *buf); +void IOPD_LW(char *buf); +void IOPD_LBU(char *buf); +void IOPD_LHU(char *buf); +void IOPD_LWR(char *buf); +void IOPD_SB(char *buf); +void IOPD_SH(char *buf); +void IOPD_SWL(char *buf); +void IOPD_SW(char *buf); +void IOPD_SWR(char *buf); +void IOPD_LWC2(char *buf); +void IOPD_SWC2(char *buf); + +void IOPD_SLL(char *buf); +void IOPD_SRL(char *buf); +void IOPD_SRA(char *buf); +void IOPD_SLLV(char *buf); +void IOPD_SRLV(char *buf); +void IOPD_SRAV(char *buf); +void IOPD_JR(char *buf); +void IOPD_JALR(char *buf); +void IOPD_SYSCALL(char *buf); +void IOPD_BREAK(char *buf); +void IOPD_MFHI(char *buf); +void IOPD_MTHI(char *buf); +void IOPD_MFLO(char *buf); +void IOPD_MTLO(char *buf); +void IOPD_MULT(char *buf); +void IOPD_MULTU(char *buf); +void IOPD_DIV(char *buf); +void IOPD_DIVU(char *buf); +void IOPD_ADD(char *buf); +void IOPD_ADDU(char *buf); +void IOPD_SUB(char *buf); +void IOPD_SUBU(char *buf); +void IOPD_AND(char *buf); +void IOPD_OR(char *buf); +void IOPD_XOR(char *buf); +void IOPD_NOR(char *buf); +void IOPD_SLT(char *buf); +void IOPD_SLTU(char *buf); + + +void IOPD_BLTZ(char *buf); +void IOPD_BGEZ(char *buf); +void IOPD_BLTZAL(char *buf); +void IOPD_BGEZAL(char *buf); + + + +void IOPD_MFC0(char *buf); +void IOPD_CFC0(char *buf); +void IOPD_MTC0(char *buf); +void IOPD_CTC0(char *buf); +void IOPD_RFE(char *buf); + + + +void IOPD_BASIC(char *buf); +void IOPD_RTPS(char *buf); +void IOPD_NCLIP(char *buf); +void IOPD_OP(char *buf); +void IOPD_DPCS(char *buf); +void IOPD_INTPL(char *buf); +void IOPD_MVMVA(char *buf); +void IOPD_NCDS(char *buf); +void IOPD_CDP(char *buf); +void IOPD_NCDT(char *buf); +void IOPD_NCCS(char *buf); +void IOPD_CC(char *buf); +void IOPD_NCS(char *buf); +void IOPD_NCT(char *buf); +void IOPD_SQR(char *buf); +void IOPD_DCPL(char *buf); +void IOPD_DPCT(char *buf); +void IOPD_AVSZ3(char *buf); +void IOPD_AVSZ4(char *buf); +void IOPD_RTPT(char *buf); +void IOPD_GPF(char *buf); +void IOPD_GPL(char *buf); +void IOPD_NCCT(char *buf); + + + +void IOPD_MFC2(char *buf); +void IOPD_CFC2(char *buf); +void IOPD_MTC2(char *buf); +void IOPD_CTC2(char *buf); +void IOPD_NULL(char *buf); + + + + void (*IOP_DEBUG_BSC[64])(char *buf) = { + IOPD_SPECIAL, IOPD_REGIMM, IOPD_J , IOPD_JAL , IOPD_BEQ , IOPD_BNE , IOPD_BLEZ, IOPD_BGTZ, + IOPD_ADDI , IOPD_ADDIU , IOPD_SLTI, IOPD_SLTIU, IOPD_ANDI, IOPD_ORI , IOPD_XORI, IOPD_LUI , + IOPD_COP0 , IOPD_NULL , IOPD_COP2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_LB , IOPD_LH , IOPD_LWL , IOPD_LW , IOPD_LBU , IOPD_LHU , IOPD_LWR , IOPD_NULL, + IOPD_SB , IOPD_SH , IOPD_SWL , IOPD_SW , IOPD_NULL, IOPD_NULL, IOPD_SWR , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_LWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_SWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + + +void (*IOP_DEBUG_SPC[64])(char *buf) = { + IOPD_SLL , IOPD_NULL , IOPD_SRL , IOPD_SRA , IOPD_SLLV , IOPD_NULL , IOPD_SRLV, IOPD_SRAV, + IOPD_JR , IOPD_JALR , IOPD_NULL, IOPD_NULL, IOPD_SYSCALL, IOPD_BREAK, IOPD_NULL, IOPD_NULL, + IOPD_MFHI, IOPD_MTHI , IOPD_MFLO, IOPD_MTLO, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_MULT, IOPD_MULTU, IOPD_DIV , IOPD_DIVU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_ADD , IOPD_ADDU , IOPD_SUB , IOPD_SUBU, IOPD_AND , IOPD_OR , IOPD_XOR , IOPD_NOR , + IOPD_NULL, IOPD_NULL , IOPD_SLT , IOPD_SLTU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_REG[32])(char *buf) = { + IOPD_BLTZ , IOPD_BGEZ , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_BLTZAL, IOPD_BGEZAL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP0[32])(char *buf) = { + IOPD_MFC0, IOPD_NULL, IOPD_CFC0, IOPD_NULL, IOPD_MTC0, IOPD_NULL, IOPD_CTC0, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_RFE , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP2[64])(char *buf) = { + IOPD_BASIC, IOPD_RTPS , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NCLIP, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_OP , IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_DPCS , IOPD_INTPL, IOPD_MVMVA, IOPD_NCDS, IOPD_CDP , IOPD_NULL , IOPD_NCDT , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NCCS, IOPD_CC , IOPD_NULL , IOPD_NCS , IOPD_NULL, + IOPD_NCT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_SQR , IOPD_DCPL , IOPD_DPCT , IOPD_NULL, IOPD_NULL, IOPD_AVSZ3, IOPD_AVSZ4, IOPD_NULL, + IOPD_RTPT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_GPF , IOPD_GPL , IOPD_NCCT +}; + +void (*IOP_DEBUG_CP2BSC[32])(char *buf) = { + IOPD_MFC2, IOPD_NULL, IOPD_CFC2, IOPD_NULL, IOPD_MTC2, IOPD_NULL, IOPD_CTC2, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +static char dbuf2[1024]; +static char obuf2[1024]; + +char *disR3000Fasm(u32 code, u32 pc) { + u32 scode = psxRegs.code; + IOP_opcode_addr = pc; + psxRegs.code = code; + IOP_DEBUG_BSC[(code) >> 26](dbuf2); + + sprintf(obuf2, "%08lX:\t%s", pc, dbuf2); + + psxRegs.code = scode; + return obuf2; +} +char *IOP_jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = (IOP_opcode_addr & 0xf0000000)|((psxRegs.code&0x3ffffff)<<2); + sprintf(buf, "0x%08lX", addr); + return buf; +} +char *IOP_offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = ((((short)( psxRegs.code & 0xFFFF) * 4) + IOP_opcode_addr + 4)); + sprintf(buf, "0x%08lX", addr); + return buf; +} +//basic table +void IOPD_SPECIAL(char *buf){IOP_DEBUG_SPC[((psxRegs.code) & 0x3F)](buf);} +void IOPD_REGIMM(char *buf){IOP_DEBUG_REG[DECODE_RT_IOP](buf);} +void IOPD_J(char *buf) { sprintf(buf, "j\t%s", IOP_jump_decode());} +void IOPD_JAL(char *buf){sprintf(buf, "jal\t%s", IOP_jump_decode());} +void IOPD_BEQ(char *buf){sprintf(buf, "beq\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BNE(char *buf){sprintf(buf, "bne\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BLEZ(char *buf){sprintf(buf, "blez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGTZ(char *buf){sprintf(buf, "bgtz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_ADDI(char *buf){sprintf(buf, "addi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ADDIU(char *buf){sprintf(buf, "addiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTI(char *buf){sprintf(buf, "slti\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTIU(char *buf){sprintf(buf, "sltiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ANDI(char *buf){sprintf(buf, "andi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ORI(char *buf){sprintf(buf, "ori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_XORI(char *buf){sprintf(buf, "xori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_LUI(char *buf){sprintf(buf, "lui\t%s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP); } +void IOPD_COP0(char *buf){IOP_DEBUG_CP0[DECODE_RS_IOP](buf);} +void IOPD_COP2(char *buf){IOP_DEBUG_CP2[((psxRegs.code) & 0x3F)](buf);} +void IOPD_LB(char *buf){sprintf(buf, "lb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LH(char *buf){sprintf(buf, "lh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWL(char *buf){sprintf(buf, "lwl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LW(char *buf){sprintf(buf, "lw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LBU(char *buf){sprintf(buf, "lbu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LHU(char *buf){sprintf(buf, "lhu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWR(char *buf){sprintf(buf, "lwr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SB(char *buf){sprintf(buf, "sb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SH(char *buf){sprintf(buf, "sh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWL(char *buf){sprintf(buf, "swl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SW(char *buf){sprintf(buf, "sw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWR(char *buf){sprintf(buf, "swr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_LWC2(char *buf){strcpy(buf, "lwc2");} +void IOPD_SWC2(char *buf){strcpy(buf, "swc2");} +//special table +void IOPD_SLL(char *buf) +{ + if (psxRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); +} +void IOPD_SRL(char *buf){sprintf(buf, "srl\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); } +void IOPD_SRA(char *buf){sprintf(buf, "sra\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP);} +void IOPD_SLLV(char *buf){sprintf(buf, "sllv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SRLV(char *buf){sprintf(buf, "srlv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SRAV(char *buf){sprintf(buf, "srav\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_JR(char *buf){sprintf(buf, "jr\t%s", GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_JALR(char *buf) +{ + int rd = DECODE_RD_IOP; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_IOP_REG[DECODE_RS_IOP]); + else + sprintf(buf, "jalr\t%s, %s", GPR_IOP_REG[rd], GPR_IOP_REG[DECODE_RS_IOP]); +} + +void IOPD_SYSCALL(char *buf){strcpy(buf, "syscall");} +void IOPD_BREAK(char *buf){strcpy(buf, "break");} +void IOPD_MFHI(char *buf){sprintf(buf, "mfhi\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTHI(char *buf){sprintf(buf, "mthi\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MFLO(char *buf){sprintf(buf, "mflo\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTLO(char *buf){sprintf(buf, "mtlo\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MULT(char *buf){sprintf(buf, "mult\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_MULTU(char *buf){sprintf(buf, "multu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIV(char *buf){sprintf(buf, "div\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIVU(char *buf){sprintf(buf, "divu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } + +void IOPD_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +//regimm + +void IOPD_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } + +//cop0 + +void IOPD_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CFC0(char *buf){ sprintf(buf, "cfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CTC0(char *buf){ sprintf(buf, "ctc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_RFE(char *buf){strcpy(buf, "rfe");} +//cop2 +void IOPD_BASIC(char *buf){IOP_DEBUG_CP2BSC[DECODE_RS_IOP](buf);} +void IOPD_RTPS(char *buf){strcpy(buf, "rtps");} +void IOPD_NCLIP(char *buf){strcpy(buf, "nclip");} +void IOPD_OP(char *buf){strcpy(buf, "op");} +void IOPD_DPCS(char *buf){strcpy(buf, "dpcs");} +void IOPD_INTPL(char *buf){strcpy(buf, "intpl");} +void IOPD_MVMVA(char *buf){strcpy(buf, "mvmva");} +void IOPD_NCDS(char *buf){strcpy(buf, "ncds");} +void IOPD_CDP(char *buf){strcpy(buf, "cdp");} +void IOPD_NCDT(char *buf){strcpy(buf, "ncdt");} +void IOPD_NCCS(char *buf){strcpy(buf, "nccs");} +void IOPD_CC(char *buf){strcpy(buf, "cc");} +void IOPD_NCS(char *buf){strcpy(buf, "ncs");} +void IOPD_NCT(char *buf){strcpy(buf, "nct");} +void IOPD_SQR(char *buf){strcpy(buf, "sqr");} +void IOPD_DCPL(char *buf){strcpy(buf, "dcpl");} +void IOPD_DPCT(char *buf){strcpy(buf, "dpct");} +void IOPD_AVSZ3(char *buf){strcpy(buf, "avsz3");} +void IOPD_AVSZ4(char *buf){strcpy(buf, "avsz4");} +void IOPD_RTPT(char *buf){strcpy(buf, "rtpt");} +void IOPD_GPF(char *buf){strcpy(buf, "gpf");} +void IOPD_GPL(char *buf){strcpy(buf, "gpl");} +void IOPD_NCCT(char *buf){strcpy(buf, "ncct");} +//cop2 basic +void IOPD_MFC2(char *buf){strcpy(buf, "mfc2");} +void IOPD_CFC2(char *buf){strcpy(buf, "cfc2");} +void IOPD_MTC2(char *buf){strcpy(buf, "mtc2");} +void IOPD_CTC2(char *buf){strcpy(buf, "ctc2");} +//null +void IOPD_NULL(char *buf){strcpy(buf, "????");} \ No newline at end of file diff --git a/DebugTools/DisR5900.c b/DebugTools/DisR5900.c new file mode 100644 index 0000000000..28ef02cab2 --- /dev/null +++ b/DebugTools/DisR5900.c @@ -0,0 +1,993 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VU.h" + +long jumpMode; +char ostr[1024]; + +// Names of registers +char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra", "hi", "lo"}; // lo,hi used in rec + +char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0" , "EntryLo1", "Context" , "PageMask" , "Wired" , "*RES*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID", + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "*RES*" , "*RES*" , "*RES*" , "Debug", + "DEPC" , "PerfCnt" , "ErrCtl" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "DESAVE"}; + +char *disRNameCP1[] = { + "FPR0" , "FPR1" , "FPR2" , "FPR3" , "FPR4" , "FPR5" , "FPR6" , "FPR7", + "FPR8" , "FPR9" , "FPR10", "FPR11", "FPR12", "FPR13", "FPR14", "FPR15", + "FPR16", "FPR17", "FPR18", "FPR19", "FPR20", "FPR21", "FPR22", "FPR23", + "FPR24", "FPR25", "FPR26", "FPR27", "FPR28", "FPR29", "FPR30", "FPR31"}; + +char *disRNameCP1c[] = { + "FRevID", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "FStatus"}; + +char *disRNameCP2f[] = { + "VF00", "VF01", "VF02", "VF03", "VF04", "VF05", "VF06", "VF07", + "VF08", "VF09", "VF10", "VF11", "VF12", "VF13", "VF14", "VF15", + "VF16", "VF17", "VF18", "VF19", "VF20", "VF21", "VF22", "VF23", + "VF24", "VF25", "VF26", "VF27", "VF28", "VF29", "VF30", "VF31"}; + +char *disRNameCP2i[] = { + "VI00", "VI01", "VI02", "VI03", "VI04", "VI05", "VI06", "VI07", + "VI08", "VI09", "VI10", "VI11", "VI12", "VI13", "VI14", "VI15", + "Status", "MAC", "Clip", "*RES*", "R", "I", "Q", "*RES*", + "*RES*", "*RES*", "TPC", "CMSAR0", "FBRST", "VPU-STAT", "*RES*", "CMSAR1"}; + +char *CP2VFnames[] = { "x", "y", "z", "w" }; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +#undef _Target_ +#undef _Branch_ +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + + +#define _rRs_ cpuRegs.GPR.r[_Rs_].UL[1], cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt_ cpuRegs.GPR.r[_Rt_].UL[1], cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd_ cpuRegs.GPR.r[_Rd_].UL[1], cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa_ cpuRegs.GPR.r[_Sa_].UL[1], cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + +#define _rFs_ cpuRegs.CP0.r[_Rd_] // Fs register + +#define _rRs32_ cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt32_ cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd32_ cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa32_ cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + + +#define _nRs_ _rRs_, disRNameGPR[_Rs_] +#define _nRt_ _rRt_, disRNameGPR[_Rt_] +#define _nRd_ _rRd_, disRNameGPR[_Rd_] +#define _nSa_ _rSa_, disRNameGPR[_Sa_] +#define _nRd0_ _rFs_, disRNameCP0[_Rd_] + +#define _nRs32_ _rRs32_, disRNameGPR[_Rs_] +#define _nRt32_ _rRt32_, disRNameGPR[_Rt_] +#define _nRd32_ _rRd32_, disRNameGPR[_Rd_] +#define _nSa32_ _rSa32_, disRNameGPR[_Sa_] + +#define _I_ _Im_, _Im_ +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR128(i) sprintf(ostr, "%s %8.8x_%8.8x_%8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64U(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], disRNameGPR[i]) +#define dGPR32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) + +#define dCP032(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.CP0.r[i], disRNameCP0[i]) + +#define dCP132(i) sprintf(ostr, "%s %f (%s),", ostr, fpuRegs.fpr[i].f, disRNameCP1[i]) +#define dCP1c32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, fpuRegs.fprc[i], disRNameCP1c[i]) +#define dCP1acc() sprintf(ostr, "%s %f (ACC),", ostr, fpuRegs.ACC.f) + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) + +#define dHI64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.HI.UL[1], cpuRegs.HI.UL[0], "hi") +#define dLO64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], "lo") +#define dImm() sprintf(ostr, "%s %4.4x (%d),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8x,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_, _Sa_) +#define dSa32() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_+32, _Sa_+32) +#define dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, cpuRegs.GPR.r[_Rs_].UL[0], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8x,", ostr, (code >> 6) & 0xffffff) +#define dSaR() sprintf(ostr, "%s %8.8x,", ostr, cpuRegs.sa) + +typedef struct { + u32 addr; + char name[32]; +} sSymbol; + +static sSymbol *dSyms = NULL; +static int nSyms = 0; + +void disR5900AddSym(u32 addr, char *name) { + dSyms = (sSymbol*)realloc(dSyms, sizeof(sSymbol) * (nSyms+1)); + if (dSyms == NULL) return; + dSyms[nSyms].addr = addr; + strncpy(dSyms[nSyms].name, name, 32); + nSyms++; +} + +void disR5900FreeSyms() { + if (dSyms != NULL) { free(dSyms); dSyms = NULL; } + nSyms = 0; +} + +char *disR5900GetSym(u32 addr) { + int i; + + if (dSyms == NULL) return NULL; + for (i=0; i laddr) { + laddr = dSyms[i].addr; + j = i; + } + } + if (j == -1) return NULL; + return dSyms[j].name; +} + +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(ostr, "%s %s", ostr, str); \ +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDI, dName("DADDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDIU, dName("DADDIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDADD, dName("DADD"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDADDU, dName("DADDU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDSUB, dName("DSUB"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDSUBU, dName("DSDBU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget(); dFindSym(_Target_);) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR32(31); dFindSym(_Target_);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR32(_Rs_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) +MakeDisF(disJALR, dName("JALR"); dGPR32(_Rs_); dGPR32(_Rd_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR64(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR64(_Rd_); dHI64();) +MakeDisF(disMFLO, dName("MFLO"); dGPR64(_Rd_); dLO64();) + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI64(); dGPR64(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO64(); dGPR64(_Rs_);) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disDSLL, dName("DSLL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSLL32, dName("DSLL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRA, dName("SRA"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRA, dName("DSRA"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRA32, dName("DSRA32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRL, dName("SRL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRL, dName("DSRL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRL32, dName("DSRL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSLLV, dName("DSLLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRAV, dName("DSRAV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRLV, dName("DSRLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWU, dName("LWU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLD, dName("LD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDL, dName("LDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDR, dName("LDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLQ, dName("LQ"); dGPR128(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSD, dName("SD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDL, dName("SDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDR, dName("SDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSQ, dName("SQ"); dGPR128(_Rt_); dOfB();) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, rd * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR32(_Rt_); dCP032(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP032(_Rd_); dGPR32(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +MakeDisF(disBGEZ, dName("BGEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + + +MakeDisF(disBEQL, dName("BEQL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNEL, dName("BNEL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBLEZL, dName("BLEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZL, dName("BGTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZL, dName("BLTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZL, dName("BGEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZALL, dName("BLTZALL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZALL, dName("BGEZALL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +MakeDisF(disBC0F, dName("BC0F"); dOffset();) +MakeDisF(disBC0T, dName("BC0T"); dOffset();) +MakeDisF(disBC0FL, dName("BC0FL"); dOffset();) +MakeDisF(disBC0TL, dName("BC0TL"); dOffset();) + +MakeDisF(disTLBR, dName("TLBR");) +MakeDisF(disTLBWI, dName("TLBWI");) +MakeDisF(disTLBWR, dName("TLBWR");) +MakeDisF(disTLBP, dName("TLBP");) +MakeDisF(disERET, dName("ERET");) +MakeDisF(disEI, dName("EI");) +MakeDisF(disDI, dName("DI");) + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +MakeDisF(disMFC1, dName("MFC1"); dGPR64(_Rt_); dCP132(_Fs_);) +MakeDisF(disCFC1, dName("CFC1"); dGPR64(_Rt_); dCP1c32(_Fs_);) +MakeDisF(disMTC1, dName("MTC1"); dCP132(_Fs_); dGPR64(_Rt_);) +MakeDisF(disCTC1, dName("CTC1"); dCP1c32(_Fs_); dGPR64(_Rt_);) + +MakeDisF(disBC1F, dName("BC1F");) +MakeDisF(disBC1T, dName("BC1T");) +MakeDisF(disBC1FL, dName("BC1FL");) +MakeDisF(disBC1TL, dName("BC1TL");) + +MakeDisF(disADDs, dName("ADDs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBs, dName("SUBs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULs, dName("MULs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disDIVs, dName("DIVs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSQRTs, dName("SQRTs"); dCP132(_Fd_); dCP132(_Ft_);) +MakeDisF(disABSs, dName("ABSs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMOVs, dName("MOVs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disNEGs, dName("NEGs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disRSQRTs, dName("RSQRTs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disADDAs, dName("ADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBAs, dName("SUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULAs, dName("MULAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDs, dName("MADDs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBs, dName("MSUBs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDAs, dName("MADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBAs, dName("MSUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCVTWs, dName("CVTWs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMAXs, dName("MAXs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMINs, dName("MINs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCFs, dName("CFs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCEQs, dName("CEQs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLTs, dName("CLTs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLEs, dName("CLEs"); dCP132(_Fs_); dCP132(_Ft_);) + +MakeDisF(disCVTSw, dName("CVTSw"); dCP132(_Fd_); dCP132(_Fs_);) + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +MakeDisF(disLWC1, dName("LWC1"); dCP132(_Rt_); dOffset();) +MakeDisF(disSWC1, dName("SWC1"); dCP132(_Rt_); dOffset();) + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +MakeDisF(disMOVZ, dName("MOVZ"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disMOVN, dName("MOVN"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ + +MakeDisF(disMULT1, dName("MULT1");) +MakeDisF(disMULTU1, dName("MULTU1");) + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADDW, dName("PADDW");) +MakeDisF(disPADDH, dName("PADDH");) +MakeDisF(disPADDB, dName("PADDB");) + +MakeDisF(disPADDSW, dName("PADDSW");) +MakeDisF(disPADDSH, dName("PADDSH");) +MakeDisF(disPADDSB, dName("PADDSB");) + +MakeDisF(disPSUBW, dName("PSUBW");) +MakeDisF(disPSUBH, dName("PSUBH");) +MakeDisF(disPSUBB, dName("PSUBB");) + +MakeDisF(disPSUBSW, dName("PSUBSW");) +MakeDisF(disPSUBSH, dName("PSUBSH");) +MakeDisF(disPSUBSB, dName("PSUBSB");) + +MakeDisF(disPCGTW, dName("PCGTW");) +MakeDisF(disPCGTH, dName("PCGTH");) +MakeDisF(disPCGTB, dName("PCGTB");) + +MakeDisF(disPMAXW, dName("PMAXW");) +MakeDisF(disPMAXH, dName("PMAXH");) + +MakeDisF(disPEXTLW, dName("PEXTLW"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLH, dName("PEXTLH"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLB, dName("PEXTLB");) +MakeDisF(disPEXTS, dName("PEXTS");) + +MakeDisF(disPPACW, dName("PPACW");) +MakeDisF(disPPACH, dName("PPACH");) +MakeDisF(disPPACB, dName("PPACB");) +MakeDisF(disPPACS, dName("PPACS");) + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADSBH, dName("PADSBH");) + +MakeDisF(disPABSW, dName("PABSW");) +MakeDisF(disPABSH, dName("PABSH");) + +MakeDisF(disPCEQW, dName("PCEQW");) +MakeDisF(disPCEQH, dName("PCEQH");) +MakeDisF(disPCEQB, dName("PCEQB");) + +MakeDisF(disPMINW, dName("PMINW");) +MakeDisF(disPMINH, dName("PMINH");) + +MakeDisF(disPADDUW, dName("PADDUW");) +MakeDisF(disPADDUH, dName("PADDUH");) +MakeDisF(disPADDUB, dName("PADDUB");) + +MakeDisF(disPSUBUW, dName("PSUBUW");) +MakeDisF(disPSUBUH, dName("PSUBUH");) +MakeDisF(disPSUBUB, dName("PSUBUB");) + +MakeDisF(disPEXTUW, dName("PEXTUW"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUH, dName("PEXTUH"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUB, dName("PEXTUB");) + +MakeDisF(disQFSRV, dName("QFSRV");) + +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDW, dName("PMADDW");) +MakeDisF(disPMADDH, dName("PMADDH");) + +MakeDisF(disPSLLVW, dName("PSLLVW");) +MakeDisF(disPSRLVW, dName("PSRLVW");) + +MakeDisF(disPMFHI, dName("PMFHI");) +MakeDisF(disPMFLO, dName("PMFLO");) + +MakeDisF(disPINTH, dName("PINTH");) + +MakeDisF(disPMULTW, dName("PMULTW");) +MakeDisF(disPMULTH, dName("PMULTH");) + +MakeDisF(disPDIVW, dName("PDIVW");) +MakeDisF(disPDIVH, dName("PDIVH");) + +MakeDisF(disPCPYLD, dName("PCPYLD"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPAND, dName("PAND"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPXOR, dName("PXOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPMSUBW, dName("PMSUBW");) +MakeDisF(disPMSUBH, dName("PMSUBH");) + +MakeDisF(disPHMADH, dName("PHMADH");) +MakeDisF(disPHMSBH, dName("PHMSBH");) + +MakeDisF(disPEXEW, dName("PEXEW");) +MakeDisF(disPEXEH, dName("PEXEH");) + +MakeDisF(disPREVH, dName("PREVH");) + +MakeDisF(disPDIVBW, dName("PDIVBW");) + +MakeDisF(disPROT3W, dName("PROT3W");) + +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDUW, dName("PMADDUW");) + +MakeDisF(disPSRAVW, dName("PSRAVW");) + +MakeDisF(disPMTHI, dName("PMTHI");) +MakeDisF(disPMTLO, dName("PMTLO");) + +MakeDisF(disPINTEH, dName("PINTEH");) + +MakeDisF(disPMULTUW, dName("PMULTUW");) +MakeDisF(disPDIVUW, dName("PDIVUW");) + +MakeDisF(disPCPYUD, dName("PCPYUD"); dGPR128(_Rd_); dGPR128(_Rt_); dGPR128(_Rs_);) + +MakeDisF(disPOR, dName("POR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPNOR, dName("PNOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPEXCH, dName("PEXCH");) +MakeDisF(disPEXCW, dName("PEXCW");) + +MakeDisF(disPCPYH, dName("PCPYH"); dGPR128(_Rd_); dGPR128(_Rt_);) + +/********************************************************* +* COP2 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X code>>24 +#define _Y code>>23 +#define _Z code>>22 +#define _W code>>21 + +MakeDisF(disLQC2, dName("LQC2"); dCP2128f(_Rt_); dOfB();) +MakeDisF(disSQC2, dName("SQC2"); dCP2128f(_Rt_); dOfB();) + +MakeDisF(disQMFC2, dName("QMFC2");) +MakeDisF(disQMTC2, dName("QMTC2");) +MakeDisF(disCFC2, dName("CFC2"); dGPR32(_Rt_); dCP232i(_Fs_);) +MakeDisF(disCTC2, dName("CTC2"); dCP232i(_Fs_); dGPR32(_Rt_);) + +MakeDisF(disBC2F, dName("BC2F");) +MakeDisF(disBC2T, dName("BC2T");) +MakeDisF(disBC2FL, dName("BC2FL");) +MakeDisF(disBC2TL, dName("BC2TL");) + +// SPEC1 +MakeDisF(disVADD, dName("VADD");) +MakeDisF(disVADDx, dName("VADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDy, dName("VADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDz, dName("VADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDw, dName("VADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDq, dName("VADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) +MakeDisF(disVADDi, dName("VADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) +MakeDisF(disVSUB, dName("VSUB");) +MakeDisF(disVSUBx, dName("VSUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBy, dName("VSUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBz, dName("VSUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBw, dName("VSUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBq, dName("VSUBq");) +MakeDisF(disVSUBi, dName("VSUBi");) +MakeDisF(disVMADD, dName("VMADD");) +MakeDisF(disVMADDx, dName("VMADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDy, dName("VMADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDz, dName("VMADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDw, dName("VMADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDq, dName("VMADDq");) +MakeDisF(disVMADDi, dName("VMADDi");) +MakeDisF(disVMSUB, dName("VMSUB");) +MakeDisF(disVMSUBx, dName("VMSUBx");) +MakeDisF(disVMSUBy, dName("VMSUBy");) +MakeDisF(disVMSUBz, dName("VMSUBz");) +MakeDisF(disVMSUBw, dName("VMSUBw");) +MakeDisF(disVMSUBq, dName("VMSUBq");) +MakeDisF(disVMSUBi, dName("VMSUBi");) +MakeDisF(disVMAX, dName("VMAX");) +MakeDisF(disVMAXx, dName("VMAXx");) +MakeDisF(disVMAXy, dName("VMAXy");) +MakeDisF(disVMAXz, dName("VMAXz");) +MakeDisF(disVMAXw, dName("VMAXw");) +MakeDisF(disVMAXi, dName("VMAXi");) +MakeDisF(disVMINI, dName("VMINI");) +MakeDisF(disVMINIx, dName("VMINIx");) +MakeDisF(disVMINIy, dName("VMINIy");) +MakeDisF(disVMINIz, dName("VMINIz");) +MakeDisF(disVMINIw, dName("VMINIw");) +MakeDisF(disVMINIi, dName("VMINIi");) +MakeDisF(disVMUL, dName("VMUL");) +MakeDisF(disVMULx, dName("VMULx");) +MakeDisF(disVMULy, dName("VMULy");) +MakeDisF(disVMULz, dName("VMULz");) +MakeDisF(disVMULw, dName("VMULw");) +MakeDisF(disVMULq, dName("VMULq");) +MakeDisF(disVMULi, dName("VMULi");) +MakeDisF(disVIADD, dName("VIADD");) +MakeDisF(disVIADDI, dName("VIADDI");) +MakeDisF(disVISUB, dName("VISUB");) +MakeDisF(disVIAND, dName("VIAND");) +MakeDisF(disVIOR, dName("VIOR");) +MakeDisF(disVOPMSUB, dName("VOPMSUB");) +MakeDisF(disVCALLMS, dName("VCALLMS");) +MakeDisF(disVCALLMSR, dName("VCALLMSR");) + +// SPEC2 +MakeDisF(disVADDA, dName("VADDA");) +MakeDisF(disVADDAx, dName("VADDAx");) +MakeDisF(disVADDAy, dName("VADDAy");) +MakeDisF(disVADDAz, dName("VADDAz");) +MakeDisF(disVADDAw, dName("VADDAw");) +MakeDisF(disVADDAq, dName("VADDAq");) +MakeDisF(disVADDAi, dName("VADDAi");) +MakeDisF(disVMADDA, dName("VMADDA");) +MakeDisF(disVMADDAx, dName("VMADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDAy, dName("VMADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDAz, dName("VMADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDAw, dName("VMADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDAq, dName("VMADDAq");) +MakeDisF(disVMADDAi, dName("VMADDAi");) +MakeDisF(disVSUBAx, dName("VSUBAx");) +MakeDisF(disVSUBAy, dName("VSUBAy");) +MakeDisF(disVSUBAz, dName("VSUBAz");) +MakeDisF(disVSUBAw, dName("VSUBAw");) +MakeDisF(disVMSUBAx, dName("VMSUBAx");) +MakeDisF(disVMSUBAy, dName("VMSUBAy");) +MakeDisF(disVMSUBAz, dName("VMSUBAz");) +MakeDisF(disVMSUBAw, dName("VMSUBAw");) +MakeDisF(disVITOF0, dName("VITOF0");) +MakeDisF(disVITOF4, dName("VITOF4");) +MakeDisF(disVITOF12, dName("VITOF12");) +MakeDisF(disVITOF15, dName("VITOF15");) +MakeDisF(disVFTOI0, dName("VFTOI0");) +MakeDisF(disVFTOI4, dName("VFTOI4");) +MakeDisF(disVFTOI12, dName("VFTOI12");) +MakeDisF(disVFTOI15, dName("VFTOI15");) +MakeDisF(disVMULA, dName("VMULA");) +MakeDisF(disVMULAx, dName("VMULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMULAy, dName("VMULAy");) +MakeDisF(disVMULAz, dName("VMULAz");) +MakeDisF(disVMULAw, dName("VMULAw");) +MakeDisF(disVMOVE, dName("VMOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_);) +MakeDisF(disVMR32, dName("VMR32");) +MakeDisF(disVDIV, dName("VDIV");) +MakeDisF(disVSQRT, dName("VSQRT"); dCP232f(_Ft_, _Ftf_);) +MakeDisF(disVRSQRT, dName("VRSQRT");) +MakeDisF(disVRNEXT, dName("VRNEXT");) +MakeDisF(disVRGET, dName("VRGET");) +MakeDisF(disVRINIT, dName("VRINIT");) +MakeDisF(disVRXOR, dName("VRXOR");) +MakeDisF(disVWAITQ, dName("VWAITQ");) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +MakeDisF(disSYNC, dName("SYNC");) +MakeDisF(disBREAK, dName("BREAK");) +MakeDisF(disSYSCALL, dName("SYSCALL"); dCode();) +MakeDisF(disCACHE, sprintf(ostr, "%s %-7s, %x,", ostr, "CACHE", _Rt_); dOfB();) +MakeDisF(disPREF, dName("PREF");) + +MakeDisF(disMFSA, dName("MFSA"); dGPR64(_Rd_); dSaR();) +MakeDisF(disMTSA, dName("MTSA"); dGPR64(_Rs_); dSaR();) + +MakeDisF(disMTSAB, dName("MTSAB");dGPR64(_Rs_); dImm();) +MakeDisF(disMTSAH, dName("MTSAH");dGPR64(_Rs_); dImm();) + +MakeDisF(disTGE, dName("TGE"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTGEU, dName("TGEU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLT, dName("TLT"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLTU, dName("TLTU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTEQ, dName("TEQ"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTNE, dName("TNE"); dGPR64(_Rs_); dGPR64(_Rt_);) + +MakeDisF(disTGEI, dName("TGEI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTGEIU, dName("TGEIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTI, dName("TLTI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTIU, dName("TLTIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTEQI, dName("TEQI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTNEI, dName("TNEI"); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + +TdisR5900F disR5900_MMI0[] = { // Subset of disMMI0 + disPADDW, disPSUBW, disPCGTW, disPMAXW, + disPADDH, disPSUBH, disPCGTH, disPMAXH, + disPADDB, disPSUBB, disPCGTB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDSW, disPSUBSW, disPEXTLW, disPPACW, + disPADDSH, disPSUBSH, disPEXTLH, disPPACH, + disPADDSB, disPSUBSB, disPEXTLB, disPPACB, + disNULL, disNULL, disPEXTS, disPPACS}; + +MakeDisF(disMMI0, disR5900_MMI0[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI1[] = { // Subset of disMMI1 + disNULL, disPABSW, disPCEQW, disPMINW, + disPADSBH, disPABSH, disPCEQH, disPMINH, + disNULL, disNULL, disPCEQB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDUW, disPSUBUW, disPEXTUW, disNULL, + disPADDUH, disPSUBUH, disPEXTUH, disNULL, + disPADDUB, disPSUBUB, disPEXTUB, disQFSRV, + disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI1, disR5900_MMI1[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI2[] = { // Subset of disMMI2 + disPMADDW, disNULL, disPSLLVW, disPSRLVW, + disPMSUBW, disNULL, disNULL, disNULL, + disPMFHI, disPMFLO, disPINTH, disNULL, + disPMULTW, disPDIVW, disPCPYLD, disNULL, + disPMADDH, disPHMADH, disPAND, disPXOR, + disPMSUBH, disPHMSBH, disNULL, disNULL, + disNULL, disNULL, disPEXEH, disPREVH, + disPMULTH, disPDIVBW, disPEXEW, disPROT3W}; + +MakeDisF(disMMI2, disR5900_MMI2[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI3[] = { // Subset of disMMI3 + disPMADDUW, disNULL, disNULL, disPSRAVW, + disNULL, disNULL, disNULL, disNULL, + disPMTHI, disPMTLO, disPINTEH, disNULL, + disPMULTUW, disPDIVUW, disPCPYUD, disNULL, + disNULL, disNULL, disPOR, disPNOR, + disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disPEXCH, disPCPYH, + disNULL, disNULL, disPEXCW, disNULL}; + +MakeDisF(disMMI3, disR5900_MMI3[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI[] = { // Subset of disMMI + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI0, disMMI2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMULT1, disMULTU1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI1, disMMI3, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI, disR5900_MMI[_Funct_] DisFInterfaceN) + + +TdisR5900F disR5900_COP0_BC0[] = { //subset of disCOP0 BC + disBC0F, disBC0T, disBC0FL, disBC0TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP0_BC0, disR5900_COP0_BC0[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP0_Func[] = { //subset of disCOP0 Function + disNULL, disTLBR, disTLBWI, disNULL, disNULL, disNULL, disTLBWR, disNULL, + disTLBP, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disERET, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disEI , disDI , disNULL , disNULL, disNULL, disNULL, disNULL , disNULL +}; +MakeDisF(disCOP0_Func, disR5900_COP0_Func[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disNULL, disNULL, disMTC0, disNULL, disNULL, disNULL, + disCOP0_BC0, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP0_Func, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR5900_COP0[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_S[] = { //subset of disCOP1 S + disADDs, disSUBs, disMULs, disDIVs, disSQRTs, disABSs, disMOVs, disNEGs, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disRSQRTs, disNULL, + disADDAs, disSUBAs, disMULAs, disNULL, disMADDs, disMSUBs, disMADDAs, disMSUBAs, + disNULL, disNULL, disNULL, disNULL, disCVTWs, disNULL, disNULL, disNULL, + disMINs, disMAXs, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCFs, disNULL, disCEQs, disNULL, disCLTs, disNULL, disCLEs, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_S, disR5900_COP1_S[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_W[] = { //subset of disCOP1 W + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCVTSw, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_W, disR5900_COP1_W[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_BC1[] = { //subset of disCOP1 BC + disBC1F, disBC1T, disBC1FL, disBC1TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_BC1, disR5900_COP1_BC1[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP1[] = { // Subset of disCOP1 + disMFC1, disNULL, disCFC1, disNULL, disMTC1, disNULL, disCTC1, disNULL, + disCOP1_BC1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP1_S, disNULL, disNULL, disNULL, disCOP1_W, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP1, disR5900_COP1[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC2[] = { //subset of disCOP2 SPEC2 + disVADDAx, disVADDAy, disVADDAz, disVADDAw, disVSUBAx, disVSUBAy, disVSUBAz, disVSUBAw, + disVMADDAx, disVMADDAy, disVMADDAz, disVMADDAw, disVMSUBAx, disVMSUBAy, disVMSUBAz, disVMSUBAw, + disVITOF0, disVITOF4, disVITOF12, disVITOF15, disVFTOI0, disVFTOI4, disVFTOI12, disVFTOI15, + disVMULAx, disVMULAy, disVMULAz, disVMULAw, disNULL, disNULL, disNULL, disNULL, + disVADDAq, disVMADDAq, disVADDAi, disVMADDAi, disNULL, disNULL, disNULL, disNULL, + disVADDA, disVMADDA, disVMULA, disNULL, disNULL, disNULL, disNULL, disNULL, + disVMOVE, disVMR32, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disVDIV, disVSQRT, disVRSQRT, disVWAITQ, disNULL, disNULL, disNULL, disNULL, + disVRNEXT, disVRGET, disVRINIT, disVRXOR, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_SPEC2, disR5900_COP2_SPEC2[(code & 0x3) | ((code >> 4) & 0x7c)] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC1[] = { //subset of disCOP2 SPEC1 + disVADDx, disVADDy, disVADDz, disVADDw, disVSUBx, disVSUBy, disVSUBz, disVSUBw, + disVMADDx, disVMADDy, disVMADDz, disVMADDw, disVMSUBx, disVMSUBy, disVMSUBz, disVMSUBw, + disVMAXx, disVMAXy, disVMAXz, disVMAXw, disVMINIx, disVMINIy, disVMINIz, disVMINIw, + disVMULx, disVMULy, disVMULz, disVMULw, disVMULq, disVMAXi, disVMULi, disVMINIi, + disVADDq, disVMADDq, disVADDi, disVMADDi, disVSUBq, disVMSUBq, disVSUBi, disVMSUBi, + disVADD, disVMADD, disVMUL, disVMAX, disVSUB, disVMSUB, disVOPMSUB, disVMINI, + disVIADD, disVISUB, disVIADDI, disNULL, disVIAND, disVIOR, disNULL, disNULL, + disVCALLMS, disVCALLMSR, disNULL, disNULL, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, +}; + +MakeDisF(disCOP2_SPEC1, disR5900_COP2_SPEC1[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_BC2[] = { //subset of disCOP2 BC + disBC2F, disBC2T, disBC2FL, disBC2TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_BC2, disR5900_COP2_BC2[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP2[] = { // Subset of disCOP2 + disNULL, disQMFC2, disCFC2, disNULL, disNULL, disQMTC2, disCTC2, disNULL, + disCOP2_BC2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1}; + +MakeDisF(disCOP2, disR5900_COP2[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_REGIMM[] = { // Subset of disREGIMM + disBLTZ, disBGEZ, disBLTZL, disBGEZL, disNULL, disNULL, disNULL, disNULL, + disTGEI, disTGEIU, disTLTI, disTLTIU, disTEQI, disNULL, disTNEI, disNULL, + disBLTZAL, disBGEZAL, disBLTZALL, disBGEZALL, disNULL, disNULL, disNULL, disNULL, + disMTSAB, disMTSAH , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disREGIMM, disR5900_REGIMM[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_SPECIAL[] = { + disSLL, disNULL, disSRL, disSRA, disSLLV, disNULL, disSRLV, disSRAV, + disJR, disJALR, disMOVZ, disMOVN, disSYSCALL, disBREAK,disNULL, disSYNC, + disMFHI, disMTHI, disMFLO, disMTLO, disDSLLV, disNULL, disDSRLV, disDSRAV, + disMULT, disMULTU,disDIV, disDIVU, disNULL, disNULL, disNULL, disNULL, + disADD, disADDU, disSUB, disSUBU, disAND, disOR, disXOR, disNOR, + disMFSA , disMTSA, disSLT, disSLTU, disDADD, disDADDU,disDSUB, disDSUBU, + disTGE, disTGEU, disTLT, disTLTU, disTEQ, disNULL, disTNE, disNULL, + disDSLL, disNULL, disDSRL, disDSRA, disDSLL32, disNULL, disDSRL32,disDSRA32 }; + +MakeDisF(disSPECIAL, disR5900_SPECIAL[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900[] = { + disSPECIAL, disREGIMM, disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI, disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disCOP1 , disCOP2, disNULL , disBEQL, disBNEL, disBLEZL, disBGTZL, + disDADDI , disDADDIU, disLDL , disLDR , disMMI , disNULL, disLQ , disSQ , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disLWU , + disSB , disSH , disSWL , disSW , disSDL , disSDR , disSWR , disCACHE, + disNULL , disLWC1 , disNULL, disPREF , disNULL, disNULL, disLQC2 , disLD , + disNULL , disSWC1 , disNULL, disNULL , disNULL, disNULL, disSQC2 , disSD }; + +MakeDisF(disR5900F, disR5900[code >> 26] DisFInterfaceN) + diff --git a/DebugTools/DisR5900asm.c b/DebugTools/DisR5900asm.c new file mode 100644 index 0000000000..8ba326fa36 --- /dev/null +++ b/DebugTools/DisR5900asm.c @@ -0,0 +1,1679 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PS2Etypes.h" +#include "Debug.h" +#include "R5900.h" +#include "DisASM.h" + +unsigned long opcode_addr; + +/* +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +/// ******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) +*/ +/*************************CPUS REGISTERS**************************/ +char *GPR_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +//floating point cop1 Floating point reg +char *COP1_REG_FP[32] ={ + "f00","f01","f02","f03","f04","f05","f06","f07", + "f08","f09","f10","f11","f12","f13","f14","f15", + "f16","f17","f18","f19","f20","f21","f21","f23", + "f24","f25","f26","f27","f28","f29","f30","f31" +}; +//floating point cop1 control registers +char *COP1_REG_FCR[32] ={ + "fcr00","fcr01","fcr02","fcr03","fcr04","fcr05","fcr06","fcr07", + "fcr08","fcr09","fcr10","fcr11","fcr12","fcr13","fcr14","fcr15", + "fcr16","fcr17","fcr18","fcr19","fcr20","fcr21","fcr21","fcr23", + "fcr24","fcr25","fcr26","fcr27","fcr28","fcr29","fcr30","fcr31" +}; + +//floating point cop2 reg +char *COP2_REG_FP[32] ={ + "vf00","vf01","vf02","vf03","vf04","vf05","vf06","vf07", + "vf08","vf09","vf10","vf11","vf12","vf13","vf14","vf15", + "vf16","vf17","vf18","vf19","vf20","vf21","vf21","vf23", + "vf24","vf25","vf26","vf27","vf28","vf29","vf30","vf31" +}; +//cop2 control registers + +char *COP2_REG_CTL[32] ={ + "vi00","vi01","vi02","vi03","vi04","vi05","vi06","vi07", + "vi08","vi09","vi10","vi11","vi12","vi13","vi14","vi15", + "Status","MACflag","ClipFlag","c2c19","R","I","Q","c2c23", + "c2c24","c2c25","TPC","CMSAR0","FBRST","VPU-STAT","c2c30","CMSAR1" +}; + + + + + +//**************************************************************** +void P_SpecialOpcode(char *buf); +void P_REGIMMOpcode(char *buf); +void P_UnknownOpcode(char *buf); +void P_COP0(char *buf); +void P_COP1(char *buf); +void P_COP2(char *buf); +void P_MMI_Unknown(char *buf); +void P_MMI(char *buf); +void P_MMI0(char *buf); +void P_MMI1(char *buf); +void P_MMI2(char *buf); +void P_MMI3(char *buf); +void P_COP0_Unknown(char *buf); +void P_COP0_BC0(char *buf); +void P_COP0_Func(char *buf); +void P_COP1_BC1(char *buf); +void P_COP1_S(char *buf); +void P_COP1_W(char *buf); +void P_COP1_Unknown(char *buf); +void P_COP2_BC2(char *buf); +void P_COP2_SPECIAL(char *buf); +void P_COP2_Unknown(char *buf); +void P_COP2_SPECIAL2(char *buf); + +// **********************Standard Opcodes************************** +void P_J(char *buf); +void P_JAL(char *buf); +void P_BEQ(char *buf); +void P_BNE(char *buf); +void P_BLEZ(char *buf); +void P_BGTZ(char *buf); +void P_ADDI(char *buf); +void P_ADDIU(char *buf); +void P_SLTI(char *buf); +void P_SLTIU(char *buf); +void P_ANDI(char *buf); +void P_ORI(char *buf); +void P_XORI(char *buf); +void P_LUI(char *buf); +void P_BEQL(char *buf); +void P_BNEL(char *buf); +void P_BLEZL(char *buf); +void P_BGTZL(char *buf); +void P_DADDI(char *buf); +void P_DADDIU(char *buf); +void P_LDL(char *buf); +void P_LDR(char *buf); +void P_LB(char *buf); +void P_LH(char *buf); +void P_LWL(char *buf); +void P_LW(char *buf); +void P_LBU(char *buf); +void P_LHU(char *buf); +void P_LWR(char *buf); +void P_LWU(char *buf); +void P_SB(char *buf); +void P_SH(char *buf); +void P_SWL(char *buf); +void P_SW(char *buf); +void P_SDL(char *buf); +void P_SDR(char *buf); +void P_SWR(char *buf); +void P_CACHE(char *buf); +void P_LWC1(char *buf); +void P_PREF(char *buf); +void P_LQC2(char *buf); +void P_LD(char *buf); +void P_SQC2(char *buf); +void P_SD(char *buf); +void P_LQ(char *buf); +void P_SQ(char *buf); +void P_SWC1(char *buf); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void P_SLL(char *buf); +void P_SRL(char *buf); +void P_SRA(char *buf); +void P_SLLV(char *buf); +void P_SRLV(char *buf); +void P_SRAV(char *buf); +void P_JR(char *buf); +void P_JALR(char *buf); +void P_SYSCALL(char *buf); +void P_BREAK(char *buf); +void P_SYNC(char *buf); +void P_MFHI(char *buf); +void P_MTHI(char *buf); +void P_MFLO(char *buf); +void P_MTLO(char *buf); +void P_DSLLV(char *buf); +void P_DSRLV(char *buf); +void P_DSRAV(char *buf); +void P_MULT(char *buf); +void P_MULTU(char *buf); +void P_DIV(char *buf); +void P_DIVU(char *buf); +void P_ADD(char *buf); +void P_ADDU(char *buf); +void P_SUB(char *buf); +void P_SUBU(char *buf); +void P_AND(char *buf); +void P_OR(char *buf); +void P_XOR(char *buf); +void P_NOR(char *buf); +void P_SLT(char *buf); +void P_SLTU(char *buf); +void P_DADD(char *buf); +void P_DADDU(char *buf); +void P_DSUB(char *buf); +void P_DSUBU(char *buf); +void P_TGE(char *buf); +void P_TGEU(char *buf); +void P_TLT(char *buf); +void P_TLTU(char *buf); +void P_TEQ(char *buf); +void P_TNE(char *buf); +void P_DSLL(char *buf); +void P_DSRL(char *buf); +void P_DSRA(char *buf); +void P_DSLL32(char *buf); +void P_DSRL32(char *buf); +void P_DSRA32(char *buf); +void P_MOVZ(char *buf); +void P_MOVN(char *buf); +void P_MFSA(char *buf); +void P_MTSA(char *buf); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void P_BLTZ(char *buf); +void P_BGEZ(char *buf); +void P_BLTZL(char *buf); +void P_BGEZL(char *buf); +void P_TGEI(char *buf); +void P_TGEIU(char *buf); +void P_TLTI(char *buf); +void P_TLTIU(char *buf); +void P_TEQI(char *buf); +void P_TNEI(char *buf); +void P_BLTZAL(char *buf); +void P_BGEZAL(char *buf); +void P_BLTZALL(char *buf); +void P_BGEZALL(char *buf); +void P_MTSAB(char *buf); +void P_MTSAH(char *buf); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void P_MADD(char *buf); +void P_MADDU(char *buf); +void P_PLZCW(char *buf); +void P_MADD1(char *buf); +void P_MADDU1(char *buf); +void P_MFHI1(char *buf); +void P_MTHI1(char *buf); +void P_MFLO1(char *buf); +void P_MTLO1(char *buf); +void P_MULT1(char *buf); +void P_MULTU1(char *buf); +void P_DIV1(char *buf); +void P_DIVU1(char *buf); +void P_PMFHL(char *buf); +void P_PMTHL(char *buf); +void P_PSLLH(char *buf); +void P_PSRLH(char *buf); +void P_PSRAH(char *buf); +void P_PSLLW(char *buf); +void P_PSRLW(char *buf); +void P_PSRAW(char *buf); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf); +void P_PSUBW(char *buf); +void P_PCGTW(char *buf); +void P_PMAXW(char *buf); +void P_PADDH(char *buf); +void P_PSUBH(char *buf); +void P_PCGTH(char *buf); +void P_PMAXH(char *buf); +void P_PADDB(char *buf); +void P_PSUBB(char *buf); +void P_PCGTB(char *buf); +void P_PADDSW(char *buf); +void P_PSUBSW(char *buf); +void P_PEXTLW(char *buf); +void P_PPACW(char *buf); +void P_PADDSH(char *buf); +void P_PSUBSH(char *buf); +void P_PEXTLH(char *buf); +void P_PPACH(char *buf); +void P_PADDSB(char *buf); +void P_PSUBSB(char *buf); +void P_PEXTLB(char *buf); +void P_PPACB(char *buf); +void P_PEXT5(char *buf); +void P_PPAC5(char *buf); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf); +void P_PCEQW(char *buf); +void P_PMINW(char *buf); +void P_PADSBH(char *buf); +void P_PABSH(char *buf); +void P_PCEQH(char *buf); +void P_PMINH(char *buf); +void P_PCEQB(char *buf); +void P_PADDUW(char *buf); +void P_PSUBUW(char *buf); +void P_PEXTUW(char *buf); +void P_PADDUH(char *buf); +void P_PSUBUH(char *buf); +void P_PEXTUH(char *buf); +void P_PADDUB(char *buf); +void P_PSUBUB(char *buf); +void P_PEXTUB(char *buf); +void P_QFSRV(char *buf); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf); +void P_PSLLVW(char *buf); +void P_PSRLVW(char *buf); +void P_PMSUBW(char *buf); +void P_PMFHI(char *buf); +void P_PMFLO(char *buf); +void P_PINTH(char *buf); +void P_PMULTW(char *buf); +void P_PDIVW(char *buf); +void P_PCPYLD(char *buf); +void P_PMADDH(char *buf); +void P_PHMADH(char *buf); +void P_PAND(char *buf); +void P_PXOR(char *buf); +void P_PMSUBH(char *buf); +void P_PHMSBH(char *buf); +void P_PEXEH(char *buf); +void P_PREVH(char *buf); +void P_PMULTH(char *buf); +void P_PDIVBW(char *buf); +void P_PEXEW(char *buf); +void P_PROT3W(char *buf); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf); +void P_PSRAVW(char *buf); +void P_PMTHI(char *buf); +void P_PMTLO(char *buf); +void P_PINTEH(char *buf); +void P_PMULTUW(char *buf); +void P_PDIVUW(char *buf); +void P_PCPYUD(char *buf); +void P_POR(char *buf); +void P_PNOR(char *buf); +void P_PEXCH(char *buf); +void P_PCPYH(char *buf); +void P_PEXCW(char *buf); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf); +void P_MTC0(char *buf); +void P_BC0F(char *buf); +void P_BC0T(char *buf); +void P_BC0FL(char *buf); +void P_BC0TL(char *buf); +void P_TLBR(char *buf); +void P_TLBWI(char *buf); +void P_TLBWR(char *buf); +void P_TLBP(char *buf); +void P_ERET(char *buf); +void P_DI(char *buf); +void P_EI(char *buf); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf); +void P_CFC1(char *buf); +void P_MTC1(char *buf); +void P_CTC1(char *buf); +void P_BC1F(char *buf); +void P_BC1T(char *buf); +void P_BC1FL(char *buf); +void P_BC1TL(char *buf); +void P_ADD_S(char *buf); +void P_SUB_S(char *buf); +void P_MUL_S(char *buf); +void P_DIV_S(char *buf); +void P_SQRT_S(char *buf); +void P_ABS_S(char *buf); +void P_MOV_S(char *buf); +void P_NEG_S(char *buf); +void P_RSQRT_S(char *buf); +void P_ADDA_S(char *buf); +void P_SUBA_S(char *buf); +void P_MULA_S(char *buf); +void P_MADD_S(char *buf); +void P_MSUB_S(char *buf); +void P_MADDA_S(char *buf); +void P_MSUBA_S(char *buf); +void P_CVT_W(char *buf); +void P_MAX_S(char *buf); +void P_MIN_S(char *buf); +void P_C_F(char *buf); +void P_C_EQ(char *buf); +void P_C_LT(char *buf); +void P_C_LE(char *buf); + void P_CVT_S(char *buf); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf); +void P_CFC2(char *buf); +void P_QMTC2(char *buf); +void P_CTC2(char *buf); +void P_BC2F(char *buf); +void P_BC2T(char *buf); +void P_BC2FL(char *buf); +void P_BC2TL(char *buf); +//*****************SPECIAL 1 VUO TABLE******************************* +void P_VADDx(char *buf); +void P_VADDy(char *buf); +void P_VADDz(char *buf); +void P_VADDw(char *buf); +void P_VSUBx(char *buf); +void P_VSUBy(char *buf); +void P_VSUBz(char *buf); +void P_VSUBw(char *buf); +void P_VMADDx(char *buf); +void P_VMADDy(char *buf); +void P_VMADDz(char *buf); +void P_VMADDw(char *buf); +void P_VMSUBx(char *buf); +void P_VMSUBy(char *buf); +void P_VMSUBz(char *buf); +void P_VMSUBw(char *buf); +void P_VMAXx(char *buf); +void P_VMAXy(char *buf); +void P_VMAXz(char *buf); +void P_VMAXw(char *buf); +void P_VMINIx(char *buf); +void P_VMINIy(char *buf); +void P_VMINIz(char *buf); +void P_VMINIw(char *buf); +void P_VMULx(char *buf); +void P_VMULy(char *buf); +void P_VMULz(char *buf); +void P_VMULw(char *buf); +void P_VMULq(char *buf); +void P_VMAXi(char *buf); +void P_VMULi(char *buf); +void P_VMINIi(char *buf); +void P_VADDq(char *buf); +void P_VMADDq(char *buf); +void P_VADDi(char *buf); +void P_VMADDi(char *buf); +void P_VSUBq(char *buf); +void P_VMSUBq(char *buf); +void P_VSUbi(char *buf); +void P_VMSUBi(char *buf); +void P_VADD(char *buf); +void P_VMADD(char *buf); +void P_VMUL(char *buf); +void P_VMAX(char *buf); +void P_VSUB(char *buf); +void P_VMSUB(char *buf); +void P_VOPMSUB(char *buf); +void P_VMINI(char *buf); +void P_VIADD(char *buf); +void P_VISUB(char *buf); +void P_VIADDI(char *buf); +void P_VIAND(char *buf); +void P_VIOR(char *buf); +void P_VCALLMS(char *buf); +void P_CALLMSR(char *buf); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf); +void P_VADDAy(char *buf); +void P_VADDAz(char *buf); +void P_VADDAw(char *buf); +void P_VSUBAx(char *buf); +void P_VSUBAy(char *buf); +void P_VSUBAz(char *buf); +void P_VSUBAw(char *buf); +void P_VMADDAx(char *buf); +void P_VMADDAy(char *buf); +void P_VMADDAz(char *buf); +void P_VMADDAw(char *buf); +void P_VMSUBAx(char *buf); +void P_VMSUBAy(char *buf); +void P_VMSUBAz(char *buf); +void P_VMSUBAw(char *buf); +void P_VITOF0(char *buf); +void P_VITOF4(char *buf); +void P_VITOF12(char *buf); +void P_VITOF15(char *buf); +void P_VFTOI0(char *buf); +void P_VFTOI4(char *buf); +void P_VFTOI12(char *buf); +void P_VFTOI15(char *buf); +void P_VMULAx(char *buf); +void P_VMULAy(char *buf); +void P_VMULAz(char *buf); +void P_VMULAw(char *buf); +void P_VMULAq(char *buf); +void P_VABS(char *buf); +void P_VMULAi(char *buf); +void P_VCLIPw(char *buf); +void P_VADDAq(char *buf); +void P_VMADDAq(char *buf); +void P_VADDAi(char *buf); +void P_VMADDAi(char *buf); +void P_VSUBAq(char *buf); +void P_VMSUBAq(char *buf); +void P_VSUBAi(char *buf); +void P_VMSUBAi(char *buf); +void P_VADDA(char *buf); +void P_VMADDA(char *buf); +void P_VMULA(char *buf); +void P_VSUBA(char *buf); +void P_VMSUBA(char *buf); +void P_VOPMULA(char *buf); +void P_VNOP(char *buf); +void P_VMONE(char *buf); +void P_VMR32(char *buf); +void P_VLQI(char *buf); +void P_VSQI(char *buf); +void P_VLQD(char *buf); +void P_VSQD(char *buf); +void P_VDIV(char *buf); +void P_VSQRT(char *buf); +void P_VRSQRT(char *buf); +void P_VWAITQ(char *buf); +void P_VMTIR(char *buf); +void P_VMFIR(char *buf); +void P_VILWR(char *buf); +void P_VISWR(char *buf); +void P_VRNEXT(char *buf); +void P_VRGET(char *buf); +void P_VRINIT(char *buf); +void P_VRXOR(char *buf); +//************************************END OF SPECIAL2 VUO TABLE**************************** + + +/* + CPU: Instructions encoded by opcode field. + 31---------26---------------------------------------------------0 + | opcode | | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | *1 | *2 | J | JAL | BEQ | BNE | BLEZ | BGTZ | +001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI | +010 | *3 | *4 | *5 | --- | BEQL | BNEL | BLEZL | BGTZL | +011 | DADDI |DADDIU | LDL | LDR | *6 | --- | LQ | SQ | +100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | +101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE | +110 | --- | LWC1 | --- | PREF | --- | --- | LQC2 | LD | +111 | --- | SWC1 | --- | --- | --- | --- | SQC2 | SD | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = SPECIAL, see SPECIAL list *2 = REGIMM, see REGIMM list + *3 = COP0 *4 = COP1 + *5 = COP2 *6 = MMI table +*/ +void (*OpcodePrintTable[64])(char *buf) = { + P_SpecialOpcode, P_REGIMMOpcode, P_J, P_JAL, P_BEQ, P_BNE, P_BLEZ, P_BGTZ, + P_ADDI, P_ADDIU, P_SLTI, P_SLTIU, P_ANDI, P_ORI, P_XORI, P_LUI, + P_COP0, P_COP1, P_COP2, P_UnknownOpcode, P_BEQL, P_BNEL, P_BLEZL, P_BGTZL, + P_DADDI, P_DADDIU, P_LDL, P_LDR, P_MMI, P_UnknownOpcode, P_LQ, P_SQ, + P_LB, P_LH, P_LWL, P_LW, P_LBU, P_LHU, P_LWR, P_LWU, + P_SB, P_SH, P_SWL, P_SW, P_SDL, P_SDR, P_SWR, P_CACHE, + P_UnknownOpcode, P_LWC1, P_UnknownOpcode, P_PREF, P_UnknownOpcode,P_UnknownOpcode, P_LQC2, P_LD, + P_UnknownOpcode, P_SWC1, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode,P_UnknownOpcode, P_SQC2, P_SD +}; + + + /* + SPECIAL: Instr. encoded by function field when opcode field = SPECIAL + 31---------26------------------------------------------5--------0 + | = SPECIAL | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | SLL | --- | SRL | SRA | SLLV | --- | SRLV | SRAV | +001 | JR | JALR | MOVZ | MOVN |SYSCALL| BREAK | --- | SYNC | +010 | MFHI | MTHI | MFLO | MTLO | DSLLV | --- | DSRLV | DSRAV | +011 | MULT | MULTU | DIV | DIVU | ---- | --- | ---- | ----- | +100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR | +101 | MFSA | MTSA | SLT | SLTU | DADD | DADDU | DSUB | DSUBU | +110 | TGE | TGEU | TLT | TLTU | TEQ | --- | TNE | --- | +111 | DSLL | --- | DSRL | DSRA |DSLL32 | --- |DSRL32 |DSRA32 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ + +void (*SpecialPrintTable[64])(char *buf) = { + P_SLL, P_UnknownOpcode, P_SRL, P_SRA, P_SLLV, P_UnknownOpcode, P_SRLV, P_SRAV, + P_JR, P_JALR, P_MOVZ, P_MOVN, P_SYSCALL, P_BREAK, P_UnknownOpcode, P_SYNC, + P_MFHI, P_MTHI, P_MFLO, P_MTLO, P_DSLLV, P_UnknownOpcode, P_DSRLV, P_DSRAV, + P_MULT, P_MULTU, P_DIV, P_DIVU, P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode, + P_ADD, P_ADDU, P_SUB, P_SUBU, P_AND, P_OR, P_XOR, P_NOR, + P_MFSA , P_MTSA , P_SLT, P_SLTU, P_DADD, P_DADDU, P_DSUB, P_DSUBU, + P_TGE, P_TGEU, P_TLT, P_TLTU, P_TEQ, P_UnknownOpcode, P_TNE, P_UnknownOpcode, + P_DSLL, P_UnknownOpcode, P_DSRL, P_DSRA, P_DSLL32, P_UnknownOpcode, P_DSRL32, P_DSRA32 +}; + +/* + REGIMM: Instructions encoded by the rt field when opcode field = REGIMM. + 31---------26----------20-------16------------------------------0 + | = REGIMM | | rt | | + ------6---------------------5------------------------------------ + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | + 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | --- | TNEI | --- | + 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | + 11 | MTSAB | MTSAH | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*REGIMMPrintTable[32])(char *buf) = { + P_BLTZ, P_BGEZ, P_BLTZL, P_BGEZL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_TGEI, P_TGEIU, P_TLTI, P_TLTIU, P_TEQI, P_UnknownOpcode, P_TNEI, P_UnknownOpcode, + P_BLTZAL, P_BGEZAL, P_BLTZALL, P_BGEZALL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_MTSAB, P_MTSAH , P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, +}; +/* + MMI: Instr. encoded by function field when opcode field = MMI + 31---------26------------------------------------------5--------0 + | = MMI | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | MADD | MADDU | --- | --- | PLZCW | --- | --- | --- | +001 | *1 | *2 | --- | --- | --- | --- | --- | --- | +010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | --- | --- | --- | --- | +011 | MULT1 | MULTU1| DIV1 | DIVU1 | --- | --- | --- | --- | +100 | MADD1 | MADDU1| --- | --- | --- | --- | --- | --- | +101 | *3 | *4 | --- | --- | --- | --- | --- | --- | +110 | PMFHL | PMTHL | --- | --- | PSLLH | --- | PSRLH | PSRAH | +111 | --- | --- | --- | --- | PSLLW | --- | PSRLW | PSRAW | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + + *1 = see MMI0 table *2 = see MMI2 Table + *3 = see MMI1 table *4 = see MMI3 Table +*/ +void (*MMIPrintTable[64])(char *buf) = { + P_MADD, P_MADDU, P_MMI_Unknown, P_MMI_Unknown, P_PLZCW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI0, P_MMI2, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MFHI1, P_MTHI1, P_MFLO1, P_MTLO1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MULT1, P_MULTU1, P_DIV1, P_DIVU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MADD1, P_MADDU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI1 , P_MMI3, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHL, P_PMTHL, P_MMI_Unknown, P_MMI_Unknown, P_PSLLH, P_MMI_Unknown, P_PSRLH, P_PSRAH, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_PSLLW, P_MMI_Unknown, P_PSRLW, P_PSRAW, +}; +/* + MMI0: Instr. encoded by function field when opcode field = MMI & MMI0 + + 31---------26------------------------------10--------6-5--------0 + | | |function | MMI0 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PADDW | PSUBW | PCGTW | PMAXW | +001 |PADDH | PSUBH | PCGTH | PMAXH | +010 |PADDB | PSUBB | PCGTB | --- | +011 | --- | --- | --- | --- | +100 |PADDSW |PSUBSW |PEXTLW | PPACW | +101 |PADDSH |PSUBSH |PEXTLH | PPACH | +110 |PADDSB |PSUBSB |PEXTLB | PPACB | +111 | --- | --- | PEXT5 | PPAC5 | + hi |-------|-------|-------|-------| +*/ +void (*MMI0PrintTable[32])(char *buf) = { + P_PADDW, P_PSUBW, P_PCGTW, P_PMAXW, + P_PADDH, P_PSUBH, P_PCGTH, P_PMAXH, + P_PADDB, P_PSUBB, P_PCGTB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDSW, P_PSUBSW, P_PEXTLW, P_PPACW, + P_PADDSH, P_PSUBSH, P_PEXTLH, P_PPACH, + P_PADDSB, P_PSUBSB, P_PEXTLB, P_PPACB, + P_MMI_Unknown, P_MMI_Unknown, P_PEXT5, P_PPAC5, +}; +/* + MMI1: Instr. encoded by function field when opcode field = MMI & MMI1 + + 31---------26------------------------------------------5--------0 + | | |function | MMI1 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 | --- | PABSW | PCEQW | PMINW | +001 |PADSBH | PABSH | PCEQH | PMINH | +010 | --- | --- | PCEQB | --- | +011 | --- | --- | --- | --- | +100 |PADDUW |PSUBUW |PEXTUW | --- | +101 |PADDUH |PSUBUH |PEXTUH | --- | +110 |PADDUB |PSUBUB |PEXTUB | QFSRV | +111 | --- | --- | --- | --- | + hi |-------|-------|-------|-------| +*/ +void (*MMI1PrintTable[32])(char *buf) = { + P_MMI_Unknown, P_PABSW, P_PCEQW, P_PMINW, + P_PADSBH, P_PABSH, P_PCEQH, P_PMINH, + P_MMI_Unknown, P_MMI_Unknown, P_PCEQB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDUW, P_PSUBUW, P_PEXTUW, P_MMI_Unknown, + P_PADDUH, P_PSUBUH, P_PEXTUH, P_MMI_Unknown, + P_PADDUB, P_PSUBUB, P_PEXTUB, P_QFSRV, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, +}; + +/* + MMI2: Instr. encoded by function field when opcode field = MMI & MMI2 + + 31---------26------------------------------------------5--------0 + | | |function | MMI2 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDW | --- |PSLLVW |PSRLVW | +001 |PMSUBW | --- | --- | --- | +010 |PMFHI |PMFLO |PINTH | --- | +011 |PMULTW |PDIVW |PCPYLD | --- | +100 |PMADDH |PHMADH | PAND | PXOR | +101 |PMSUBH |PHMSBH | --- | --- | +110 | --- | --- | PEXEH | PREVH | +111 |PMULTH |PDIVBW | PEXEW |PROT3W | + hi |-------|-------|-------|-------| +*/ +void (*MMI2PrintTable[32])(char *buf) = { + P_PMADDW, P_MMI_Unknown, P_PSLLVW, P_PSRLVW, + P_PMSUBW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHI, P_PMFLO, P_PINTH, P_MMI_Unknown, + P_PMULTW, P_PDIVW, P_PCPYLD, P_MMI_Unknown, + P_PMADDH, P_PHMADH, P_PAND, P_PXOR, + P_PMSUBH, P_PHMSBH, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXEH, P_PREVH, + P_PMULTH, P_PDIVBW, P_PEXEW, P_PROT3W, +}; +/* + MMI3: Instr. encoded by function field when opcode field = MMI & MMI3 + 31---------26------------------------------------------5--------0 + | | |function | MMI3 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDUW| --- | --- |PSRAVW | +001 | --- | --- | --- | --- | +010 |PMTHI | PMTLO |PINTEH | --- | +011 |PMULTUW| PDIVUW|PCPYUD | --- | +100 | --- | --- | POR | PNOR | +101 | --- | --- | --- | --- | +110 | --- | --- | PEXCH | PCPYH | +111 | --- | --- | PEXCW | --- | + hi |-------|-------|-------|-------| + */ +void (*MMI3PrintTable[32])(char *buf) = { + P_PMADDUW, P_MMI_Unknown, P_MMI_Unknown, P_PSRAVW, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMTHI, P_PMTLO, P_PINTEH, P_MMI_Unknown, + P_PMULTUW, P_PDIVUW, P_PCPYUD, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_POR, P_PNOR, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCH, P_PCPYH, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCW, P_MMI_Unknown, +}; +/* + COP0: Instructions encoded by the rs field when opcode = COP0. + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC0 | --- | --- | --- | MTC0 | --- | --- | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=BC See BC0 list *2 = TLB instr, see TLB list +*/ +void (*COP0PrintTable[32])(char *buf) = { + P_MFC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_MTC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_BC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Func, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + BC0: Instructions encoded by the rt field when opcode = COP0 & rs field=BC0 + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0BC0PrintTable[32])(char *buf) = { + P_BC0F, P_BC0T, P_BC0FL, P_BC0TL, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + C0=Instructions encode by function field when Opcode field=COP0 & rs field=C0 + 31---------26------------------------------------------5--------0 + | | | | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- | +001 | TLBP | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | ERET | --- | --- | --- | --- | --- | --- | --- | +100 | --- | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | EI | DI | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0C0PrintTable[64])(char *buf) = { + P_COP0_Unknown, P_TLBR, P_TLBWI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_TLBWR, P_COP0_Unknown, + P_TLBP, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_ERET, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_EI, P_DI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown +}; +/* + COP1: Instructions encoded by the fmt field when opcode = COP1. + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC1 | --- | CFC1 | --- | MTC1 | --- | CTC1 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | *3 | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC1 list *2 = S instr, see FPU list + *3 = W instr, see FPU list +*/ +void (*COP1PrintTable[32])(char *buf) = { + P_MFC1, P_COP1_Unknown, P_CFC1, P_COP1_Unknown, P_MTC1, P_COP1_Unknown, P_CTC1, P_COP1_Unknown, + P_COP1_BC1, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_S, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_W, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + BC1: Instructions encoded by the rt field when opcode = COP1 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1BC1PrintTable[32])(char *buf) = { + P_BC1F, P_BC1T, P_BC1FL, P_BC1TL, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = S + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = S | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | ADD.S | SUB.S | MUL.S | DIV.S | SQRT.S| ABS.S | MOV.S | NEG.S | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- |RSQRT.S| --- | +011 | ADDA.S| SUBA.S| MULA.S| --- | MADD.S| MSUB.S|MADDA.S|MSUBA.S| +100 | --- | --- | --- | --- | CVT.W | --- | --- | --- | +101 | MAX.S | MIN.S | --- | --- | --- | --- | --- | --- | +110 | C.F | --- | C.EQ | --- | C.LT | --- | C.LE | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1SPrintTable[64])(char *buf) = { +P_ADD_S, P_SUB_S, P_MUL_S, P_DIV_S, P_SQRT_S, P_ABS_S, P_MOV_S, P_NEG_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_RSQRT_S, P_COP1_Unknown, +P_ADDA_S, P_SUBA_S, P_MULA_S, P_COP1_Unknown,P_MADD_S, P_MSUB_S, P_MADDA_S, P_MSUBA_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_CVT_W, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_MAX_S, P_MIN_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_C_F, P_COP1_Unknown,P_C_EQ, P_COP1_Unknown,P_C_LT, P_COP1_Unknown,P_C_LE, P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = W + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = W | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | --- | --- | --- | --- | --- | --- | --- | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | --- | --- | --- | --- | --- | --- | --- | --- | +100 | CVT.S | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1WPrintTable[64])(char *buf) = { +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_CVT_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; + +//************************************************************* +//COP2 TABLES :) +//************************************************************* +/* + COP2: Instructions encoded by the fmt field when opcode = COP2. + 31--------26-25------21 ----------------------------------------0 + | = COP2 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | --- | QMFC2 | CFC2 | --- | --- | QMTC2 | CTC2 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC2 list *2 =see special1 table +*/ +void (*COP2PrintTable[32])(char *buf) = { + P_COP2_Unknown, P_QMFC2, P_CFC2, P_COP2_Unknown, P_COP2_Unknown, P_QMTC2, P_CTC2, P_COP2_Unknown, + P_COP2_BC2, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + + +}; +/* + BC2: Instructions encoded by the rt field when opcode = COP2 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP2 | rs=BC2| | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC2F | BC2T | BC2FL | BC2TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + */ +void (*COP2BC2PrintTable[32])(char *buf) = { + P_BC2F, P_BC2T, P_BC2FL, P_BC2TL, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, +}; +/* + Special1 table : instructions encode by function field when opcode=COP2 & rs field=Special1 + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 |VADDx |VADDy |VADDz |VADDw |VSUBx |VSUBy |VSUBz |VSUBw | +001 |VMADDx |VMADDy |VMADDz |VMADDw |VMSUBx |VMSUBy |VMSUBz |VMSUBw | +010 |VMAXx |VMAXy |VMAXz |VMAXw |VMINIx |VMINIy |VMINIz |VMINIw | +011 |VMULx |VMULy |VMULz |VMULw |VMULq |VMAXi |VMULi |VMINIi | +100 |VADDq |VMADDq |VADDi |VMADDi |VSUBq |VMSUBq |VSUbi |VMSUBi | +101 |VADD |VMADD |VMUL |VMAX |VSUB |VMSUB |VOPMSUB|VMINI | +110 |VIADD |VISUB |VIADDI | --- |VIAND |VIOR | --- | --- | +111 |VCALLMS|CALLMSR| --- | --- | *1 | *1 | *1 | *1 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=see special2 table +*/ +void (*COP2SPECIAL1PrintTable[64])(char *buf) = +{ + P_VADDx, P_VADDy, P_VADDz, P_VADDw, P_VSUBx, P_VSUBy, P_VSUBz, P_VSUBw, + P_VMADDx, P_VMADDy, P_VMADDz, P_VMADDw, P_VMSUBx, P_VMSUBy, P_VMSUBz, P_VMSUBw, + P_VMAXx, P_VMAXy, P_VMAXz, P_VMAXw, P_VMINIx, P_VMINIy, P_VMINIz, P_VMINIw, + P_VMULx, P_VMULy, P_VMULz, P_VMULw, P_VMULq, P_VMAXi, P_VMULi, P_VMINIi, + P_VADDq, P_VMADDq, P_VADDi, P_VMADDi, P_VSUBq, P_VMSUBq, P_VSUbi, P_VMSUBi, + P_VADD, P_VMADD, P_VMUL, P_VMAX, P_VSUB, P_VMSUB, P_VOPMSUB, P_VMINI, + P_VIADD, P_VISUB, P_VIADDI, P_COP2_Unknown,P_VIAND, P_VIOR, P_COP2_Unknown, P_COP2_Unknown, + P_VCALLMS, P_CALLMSR, P_COP2_Unknown,P_COP2_Unknown,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2, + +}; +/* + Special2 table : instructions encode by function field when opcode=COp2 & rs field=Special2 + + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special2 | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +0000 |VADDAx |VADDAy |VADDAz |VADDAw |VSUBAx |VSUBAy |VSUBAz |VSUBAw | +0001 |VMADDAx|VMADDAy|VMADDAz|VMADDAw|VMSUBAx|VMSUBAy|VMSUBAz|VMSUBAw| +0010 |VITOF0 |VITOF4 |VITOF12|VITOF15|VFTOI0 |VFTOI4 |VFTOI12|VFTOI15| +0011 |VMULAx |VMULAy |VMULAz |VMULAw |VMULAq |VABS |VMULAi |VCLIPw | +0100 |VADDAq |VMADDAq|VADDAi |VMADDAi|VSUBAq |VMSUBAq|VSUBAi |VMSUBAi| +0101 |VADDA |VMADDA |VMULA | --- |VSUBA |VMSUBA |VOPMULA|VNOP | +0110 |VMONE |VMR32 | --- | --- |VLQI |VSQI |VLQD |VSQD | +0111 |VDIV |VSQRT |VRSQRT |VWAITQ |VMTIR |VMFIR |VILWR |VISWR | +1000 |VRNEXT |VRGET |VRINIT |VRXOR | --- | --- | --- | --- | +1001 | --- | --- | --- | --- | --- | --- | --- | --- | +1010 | --- | --- | --- | --- | --- | --- | --- | --- | +1011 | --- | --- | --- | --- | --- | --- | --- | --- | +1100 | --- | --- | --- | --- | --- | --- | --- | --- | +1101 | --- | --- | --- | --- | --- | --- | --- | --- | +1110 | --- | --- | --- | --- | --- | --- | --- | --- | +1111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP2SPECIAL2PrintTable[128])(char *buf) = +{ + P_VADDAx ,P_VADDAy ,P_VADDAz ,P_VADDAw ,P_VSUBAx ,P_VSUBAy ,P_VSUBAz ,P_VSUBAw, + P_VMADDAx ,P_VMADDAy ,P_VMADDAz ,P_VMADDAw ,P_VMSUBAx ,P_VMSUBAy ,P_VMSUBAz ,P_VMSUBAw, + P_VITOF0 ,P_VITOF4 ,P_VITOF12 ,P_VITOF15 ,P_VFTOI0 ,P_VFTOI4 ,P_VFTOI12 ,P_VFTOI15, + P_VMULAx ,P_VMULAy ,P_VMULAz ,P_VMULAw ,P_VMULAq ,P_VABS ,P_VMULAi ,P_VCLIPw, + P_VADDAq ,P_VMADDAq ,P_VADDAi ,P_VMADDAi ,P_VSUBAq ,P_VMSUBAq ,P_VSUBAi ,P_VMSUBAi, + P_VADDA ,P_VMADDA ,P_VMULA ,P_COP2_Unknown,P_VSUBA ,P_VMSUBA ,P_VOPMULA ,P_VNOP, + P_VMONE ,P_VMR32 ,P_COP2_Unknown,P_COP2_Unknown,P_VLQI ,P_VSQI ,P_VLQD ,P_VSQD, + P_VDIV ,P_VSQRT ,P_VRSQRT ,P_VWAITQ ,P_VMTIR ,P_VMFIR ,P_VILWR ,P_VISWR, + P_VRNEXT ,P_VRGET ,P_VRINIT ,P_VRXOR ,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, +}; + +//**************************TABLES CALLS*********************** + +static char dbuf[1024]; +static char obuf[1024]; + +char *disR5900Fasm(u32 code, u32 pc) { + u32 scode = cpuRegs.code; + opcode_addr = pc; + cpuRegs.code = code; + OpcodePrintTable[(code) >> 26](dbuf); + + sprintf(obuf, "%08X:\t%s", pc, dbuf); + + cpuRegs.code = scode; + return obuf; +} + +void P_SpecialOpcode(char *buf) +{ + SpecialPrintTable[DECODE_FUNCTION](buf); +} +void P_REGIMMOpcode(char *buf) +{ + REGIMMPrintTable[DECODE_RT](buf); +} + +//***********COP0 TABLE CALLS******************************** + +void P_COP0(char *buf) +{ + COP0PrintTable[DECODE_RS](buf); +} +void P_COP0_BC0(char *buf) +{ + + COP0BC0PrintTable[DECODE_C0BC](buf); +} +void P_COP0_Func(char *buf) +{ + + COP0C0PrintTable[DECODE_FUNCTION](buf); +} + +//*****************MMI TABLES CALLS************************** +void P_MMI(char *buf) +{ + + MMIPrintTable[DECODE_FUNCTION](buf); +} +void P_MMI0(char *buf) +{ + MMI0PrintTable[DECODE_SA](buf); +} +void P_MMI1(char *buf) +{ + MMI1PrintTable[DECODE_SA](buf); +} +void P_MMI2(char *buf) +{ + MMI2PrintTable[DECODE_SA](buf); +} +void P_MMI3(char *buf) +{ + MMI3PrintTable[DECODE_SA](buf); +} +//****************END OF MMI TABLES CALLS********************** +//COP1 TABLECALLS******************************************* +void P_COP1(char *buf) +{ + + COP1PrintTable[DECODE_RS](buf); +} +void P_COP1_BC1(char *buf) +{ + COP1BC1PrintTable[DECODE_C1BC](buf); +} +void P_COP1_S(char *buf) +{ + COP1SPrintTable[DECODE_FUNCTION](buf); +} +void P_COP1_W(char *buf) +{ + COP1WPrintTable[DECODE_FUNCTION](buf); +} +//**********************END OF COP1 TABLE CALLS + +//************************************************************* +//************************COP2********************************** +void P_COP2(char *buf) +{ + + COP2PrintTable[DECODE_RS](buf); +} +void P_COP2_BC2(char *buf) +{ + COP2BC2PrintTable[DECODE_C2BC](buf); +} +void P_COP2_SPECIAL(char *buf) +{ + COP2SPECIAL1PrintTable[DECODE_FUNCTION ](buf); + +} +void P_COP2_SPECIAL2(char *buf) +{ + + COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](buf); + +} + +//**************************UNKNOWN**************************** +void P_UnknownOpcode(char *buf) +{ + strcpy(buf, "?????"); +} +void P_COP0_Unknown(char *buf) +{ + strcpy(buf, "COP0 ??"); +} +void P_COP1_Unknown(char *buf) +{ + strcpy(buf, "COP1 ??"); +} +void P_COP2_Unknown(char *buf) +{ + strcpy(buf,"COP2 ??"); +} + +void P_MMI_Unknown(char *buf) +{ + strcpy(buf,"MMI ??"); +} + + + +//************************************************************* + +//*****************SOME DECODE STUFF*************************** +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(buf, "%s %s", buf, str); \ +} + +char *jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_JUMP; + sprintf(buf, "0x%08X", addr); + + dFindSym(addr); + return buf; +} + +char *offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_OFFSET; + sprintf(buf, "0x%08X", addr); + dFindSym(addr); + return buf; +} + +//*********************END OF DECODE ROUTINES****************** + +//********************* Standard Opcodes*********************** +void P_J(char *buf) { sprintf(buf, "j\t%s", jump_decode());} +void P_JAL(char *buf) { sprintf(buf, "jal\t%s", jump_decode());} +void P_BEQ(char *buf) { sprintf(buf, "beq\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNE(char *buf) { sprintf(buf, "bne\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZ(char *buf) { sprintf(buf, "blez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZ(char *buf) { sprintf(buf, "bgtz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_ADDI(char *buf) { sprintf(buf, "addi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ADDIU(char *buf) { sprintf(buf, "addiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_SLTI(char *buf) { sprintf(buf, "slti\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_SLTIU(char *buf) { sprintf(buf, "sltiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_ANDI(char *buf) { sprintf(buf, "andi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ORI(char *buf) { sprintf(buf, "ori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_XORI(char *buf) { sprintf(buf, "xori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LUI(char *buf) { sprintf(buf, "lui\t%s, 0x%04X", GPR_REG[DECODE_RT], DECODE_IMMED); } +void P_BEQL(char *buf) { sprintf(buf, "beql\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNEL(char *buf) { sprintf(buf, "bnel\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZL(char *buf) { sprintf(buf, "blezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZL(char *buf) { sprintf(buf, "bgtzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_DADDI(char *buf) { sprintf(buf, "daddi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_DADDIU(char *buf) { sprintf(buf, "daddiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LDL(char *buf) { sprintf(buf, "ldl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LDR(char *buf) { sprintf(buf, "ldr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LB(char *buf) { sprintf(buf, "lb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LH(char *buf) { sprintf(buf, "lh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWL(char *buf) { sprintf(buf, "lwl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LW(char *buf) { sprintf(buf, "lw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LBU(char *buf) { sprintf(buf, "lbu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LHU(char *buf) { sprintf(buf, "lhu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWR(char *buf) { sprintf(buf, "lwr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWU(char *buf) { sprintf(buf, "lwu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SB(char *buf) { sprintf(buf, "sb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SH(char *buf) { sprintf(buf, "sh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWL(char *buf) { sprintf(buf, "swl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SW(char *buf) { sprintf(buf, "sw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDL(char *buf) { sprintf(buf, "sdl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDR(char *buf) { sprintf(buf, "sdr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWR(char *buf) { sprintf(buf, "swr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LD(char *buf) { sprintf(buf, "ld\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SD(char *buf) { sprintf(buf, "sd\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQ(char *buf) { sprintf(buf, "lq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQ(char *buf) { sprintf(buf, "sq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWC1(char *buf) { sprintf(buf, "swc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQC2(char *buf) { sprintf(buf, "sqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_PREF(char *buf) { strcpy(buf, "pref ---");/*sprintf(buf, "PREF\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[RS]); */} +void P_LWC1(char *buf) { sprintf(buf, "lwc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQC2(char *buf) { sprintf(buf, "lqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +//********************END OF STANDARD OPCODES************************* + +void P_SLL(char *buf) +{ + if (cpuRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); +} + +void P_SRL(char *buf) { sprintf(buf, "srl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SRA(char *buf) { sprintf(buf, "sra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SLLV(char *buf) { sprintf(buf, "sllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_SRLV(char *buf) { sprintf(buf, "srlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]);} +void P_SRAV(char *buf) { sprintf(buf, "srav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_JR(char *buf) { sprintf(buf, "jr\t%s", GPR_REG[DECODE_RS]); } + +void P_JALR(char *buf) +{ + int rd = DECODE_RD; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_REG[DECODE_RS]); + else + sprintf(buf, "jalr\t%s, %s", GPR_REG[rd], GPR_REG[DECODE_RS]); +} + + +void P_SYNC(char *buf) { sprintf(buf, "SYNC");} +void P_MFHI(char *buf) { sprintf(buf, "mfhi\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI(char *buf) { sprintf(buf, "mthi\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO(char *buf) { sprintf(buf, "mflo\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO(char *buf) { sprintf(buf, "mtlo\t%s", GPR_REG[DECODE_RS]); } +void P_DSLLV(char *buf) { sprintf(buf, "dsllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRLV(char *buf) { sprintf(buf, "dsrlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRAV(char *buf) { sprintf(buf, "dsrav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_MULT(char *buf) { sprintf(buf, "mult\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_MULTU(char *buf) { sprintf(buf, "multu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV(char *buf) { sprintf(buf, "div\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU(char *buf) { sprintf(buf, "divu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADD(char *buf) { sprintf(buf, "dadd\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADDU(char *buf) { sprintf(buf, "daddu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUB(char *buf) { sprintf(buf, "dsub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUBU(char *buf) { sprintf(buf, "dsubu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGE(char *buf) { sprintf(buf, "tge\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGEU(char *buf) { sprintf(buf, "tgeu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLT(char *buf) { sprintf(buf, "tlt\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLTU(char *buf) { sprintf(buf, "tltu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TEQ(char *buf) { sprintf(buf, "teq\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TNE(char *buf) { sprintf(buf, "tne\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSLL(char *buf) { sprintf(buf, "dsll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL(char *buf) { sprintf(buf, "dsrl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA(char *buf) { sprintf(buf, "dsra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSLL32(char *buf) { sprintf(buf, "dsll32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL32(char *buf) { sprintf(buf, "dsrl32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA32(char *buf) { sprintf(buf, "dsra32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_MOVZ(char *buf) { sprintf(buf, "movz\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MOVN(char *buf) { sprintf(buf, "movn\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFSA(char *buf) { sprintf(buf, "mfsa\t%s", GPR_REG[DECODE_RD]);} +void P_MTSA(char *buf) { sprintf(buf, "mtsa\t%s", GPR_REG[DECODE_RS]);} +//*** unsupport (yet) cpu opcodes +void P_SYSCALL(char *buf) { strcpy(buf, "syscall ---");/*sprintf(buf, "syscall\t0x%05X", DECODE_SYSCALL);*/} +void P_BREAK(char *buf) { strcpy(buf, "break ---");/*sprintf(buf, "break\t0x%05X", DECODE_BREAK); */} +void P_CACHE(char *buf) { strcpy(buf, "cache ---");/*sprintf(buf, "cache\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); */} +//************************REGIMM OPCODES*************************** +void P_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZL(char *buf) { sprintf(buf, "bltzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZL(char *buf) { sprintf(buf, "bgezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_TGEI(char *buf) { sprintf(buf, "tgei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TGEIU(char *buf) { sprintf(buf, "tgeiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTI(char *buf) { sprintf(buf, "tlti\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTIU(char *buf) { sprintf(buf, "tltiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TEQI(char *buf) { sprintf(buf, "teqi\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TNEI(char *buf) { sprintf(buf, "tnei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZALL(char *buf) { sprintf(buf, "bltzall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZALL(char *buf) { sprintf(buf, "bgezall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_MTSAB(char *buf) { sprintf(buf, "mtsab\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_MTSAH(char *buf) { sprintf(buf, "mtsah\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} + + +//***************************SPECIAL 2 CPU OPCODES******************* +const char* pmfhl_sub[] = { "lw", "uw", "slw", "lh", "sh" }; + +void P_MADD(char *buf) { sprintf(buf, "madd\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU(char *buf) { sprintf(buf, "maddu\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_PLZCW(char *buf) { sprintf(buf, "plzcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS]); } +void P_MADD1(char *buf) { sprintf(buf, "madd1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU1(char *buf) { sprintf(buf, "maddu1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFHI1(char *buf) { sprintf(buf, "mfhi1\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI1(char *buf) { sprintf(buf, "mthi1\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO1(char *buf) { sprintf(buf, "mflo1\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO1(char *buf) { sprintf(buf, "mtlo1\t%s", GPR_REG[DECODE_RS]); } +void P_MULT1(char *buf) { sprintf(buf, "mult1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MULTU1(char *buf) { sprintf(buf, "multu1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV1(char *buf) { sprintf(buf, "div1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU1(char *buf) { sprintf(buf, "divu1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//that have parametres that i haven't figure out how to display... +void P_PMFHL(char *buf) { sprintf(buf, "pmfhl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RD]); } +void P_PMTHL(char *buf) { sprintf(buf, "pmthl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RS]); } +void P_PSLLH(char *buf) { sprintf(buf, "psllh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_PSRLH(char *buf) { sprintf(buf, "psrlh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAH(char *buf) { sprintf(buf, "psrah \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSLLW(char *buf) { sprintf(buf, "psllw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRLW(char *buf) { sprintf(buf, "psrlw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAW(char *buf) { sprintf(buf, "psraw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +//***************************END OF SPECIAL OPCODES****************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf){ sprintf(buf, "paddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBW(char *buf){ sprintf(buf, "psubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTW(char *buf){ sprintf(buf, "pcgtw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXW(char *buf){ sprintf(buf, "pmaxw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDH(char *buf){ sprintf(buf, "paddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBH(char *buf){ sprintf(buf, "psubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTH(char *buf){ sprintf(buf, "pcgth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXH(char *buf){ sprintf(buf, "pmaxh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDB(char *buf){ sprintf(buf, "paddb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBB(char *buf){ sprintf(buf, "psubb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTB(char *buf){ sprintf(buf, "pcgtb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSW(char *buf){ sprintf(buf, "paddsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSW(char *buf){ sprintf(buf, "psubsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLW(char *buf){ sprintf(buf, "pextlw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACW(char *buf) { sprintf(buf, "ppacw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSH(char *buf){ sprintf(buf, "paddsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSH(char *buf){ sprintf(buf, "psubsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLH(char *buf){ sprintf(buf, "pextlh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACH(char *buf) { sprintf(buf, "ppach\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSB(char *buf){ sprintf(buf, "paddsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSB(char *buf){ sprintf(buf, "psubsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLB(char *buf){ sprintf(buf, "pextlb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACB(char *buf) { sprintf(buf, "ppacb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXT5(char *buf) { sprintf(buf, "pext5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PPAC5(char *buf) { sprintf(buf, "ppac5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//**********END OF MMI0 OPCODES********************************* +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf){ sprintf(buf, "pabsw%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQW(char *buf){ sprintf(buf, "pceqw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINW(char *buf){ sprintf(buf, "pminw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADSBH(char *buf){ sprintf(buf, "padsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PABSH(char *buf){ sprintf(buf, "pabsh%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQH(char *buf){ sprintf(buf, "pceqh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINH(char *buf){ sprintf(buf, "pminh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCEQB(char *buf){ sprintf(buf, "pceqb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUW(char *buf){ sprintf(buf, "padduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUW(char *buf){ sprintf(buf, "psubuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUW(char *buf){ sprintf(buf, "pextuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUH(char *buf){ sprintf(buf, "padduh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUH(char *buf){ sprintf(buf, "psubuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUH(char *buf){ sprintf(buf, "pextuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUB(char *buf){ sprintf(buf, "paddub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUB(char *buf){ sprintf(buf, "psubub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUB(char *buf){ sprintf(buf, "pextub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_QFSRV(char *buf) { sprintf(buf, "qfsrv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf){ sprintf(buf, "pmaddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSLLVW(char *buf){ sprintf(buf, "psllvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSRLVW(char *buf){ sprintf(buf, "psrlvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBW(char *buf){ sprintf(buf, "msubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMFHI(char *buf){ sprintf(buf, "pmfhi\t%s", GPR_REG[DECODE_RD]); } +void P_PMFLO(char *buf){ sprintf(buf, "pmflo\t%s", GPR_REG[DECODE_RD]); } +void P_PINTH(char *buf){ sprintf(buf, "pinth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTW(char *buf){ sprintf(buf, "pmultw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVW(char *buf){ sprintf(buf, "pdivw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYLD(char *buf){ sprintf(buf, "pcpyld\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMADDH(char *buf){ sprintf(buf, "pmaddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMADH(char *buf){ sprintf(buf, "phmadh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PAND(char *buf){ sprintf(buf, "pand\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PXOR(char *buf){ sprintf(buf, "pxor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBH(char *buf){ sprintf(buf, "pmsubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMSBH(char *buf){ sprintf(buf, "phmsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEH(char *buf){ sprintf(buf, "pexeh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PREVH(char *buf){ sprintf(buf, "prevh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PMULTH(char *buf){ sprintf(buf, "pmulth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVBW(char *buf){ sprintf(buf, "pdivbw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEW(char *buf){ sprintf(buf, "pexew\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PROT3W(char *buf){ sprintf(buf, "prot3w\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf){ sprintf(buf, "pmadduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PSRAVW(char *buf){ sprintf(buf, "psravw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PMTHI(char *buf){ sprintf(buf, "pmthi\t%s", GPR_REG[DECODE_RS]); } +void P_PMTLO(char *buf){ sprintf(buf, "pmtlo\t%s", GPR_REG[DECODE_RS]); } +void P_PINTEH(char *buf){ sprintf(buf, "pinteh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTUW(char *buf){ sprintf(buf, "pmultuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVUW(char *buf){ sprintf(buf, "pdivuw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYUD(char *buf){ sprintf(buf, "pcpyud\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_POR(char *buf){ sprintf(buf, "por\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PNOR(char *buf){ sprintf(buf, "pnor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXCH(char *buf){ sprintf(buf, "pexch\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PCPYH(char *buf){ sprintf(buf, "pcpyh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PEXCW(char *buf){ sprintf(buf, "pexcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_BC0F(char *buf){ sprintf(buf, "bc0f\t%s", offset_decode()); } +void P_BC0T(char *buf){ sprintf(buf, "bc0t\t%s", offset_decode()); } +void P_BC0FL(char *buf){ sprintf(buf, "bc0fl\t%s", offset_decode()); } +void P_BC0TL(char *buf){ sprintf(buf, "bc0tl\t%s", offset_decode()); } +void P_TLBR(char *buf){ strcpy(buf,"tlbr");} +void P_TLBWI(char *buf){ strcpy(buf,"tlbwi");} +void P_TLBWR(char *buf){ strcpy(buf,"tlbwr");} +void P_TLBP(char *buf){ strcpy(buf,"tlbp");} +void P_ERET(char *buf){ strcpy(buf,"eret");} +void P_DI(char *buf){ strcpy(buf,"di");} +void P_EI(char *buf){ strcpy(buf,"ei");} +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf){ sprintf(buf, "mfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CFC1(char *buf){ sprintf(buf, "cfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_MTC1(char *buf){ sprintf(buf, "mtc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CTC1(char *buf){ sprintf(buf, "ctc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_BC1F(char *buf){ sprintf(buf, "bc1f\t%s", offset_decode()); } +void P_BC1T(char *buf){ sprintf(buf, "bc1t\t%s", offset_decode()); } +void P_BC1FL(char *buf){ sprintf(buf, "bc1fl\t%s", offset_decode()); } +void P_BC1TL(char *buf){ sprintf(buf, "bc1tl\t%s", offset_decode()); } +void P_ADD_S(char *buf){ sprintf(buf, "add.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_SUB_S(char *buf){ sprintf(buf, "sub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MUL_S(char *buf){ sprintf(buf, "mul.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_DIV_S(char *buf){ sprintf(buf, "div.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SQRT_S(char *buf){ sprintf(buf, "sqrt.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FT]); } +void P_ABS_S(char *buf){ sprintf(buf, "abs.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MOV_S(char *buf){ sprintf(buf, "mov.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_NEG_S(char *buf){ sprintf(buf, "neg.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]);} +void P_RSQRT_S(char *buf){sprintf(buf, "rsqrt.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_ADDA_S(char *buf){ sprintf(buf, "adda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SUBA_S(char *buf){ sprintf(buf, "suba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MULA_S(char *buf){ sprintf(buf, "mula.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADD_S(char *buf){ sprintf(buf, "madd.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUB_S(char *buf){ sprintf(buf, "msub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADDA_S(char *buf){sprintf(buf, "madda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUBA_S(char *buf){sprintf(buf, "msuba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_W(char *buf){ sprintf(buf, "cvt.w.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MAX_S(char *buf){ sprintf(buf, "max.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MIN_S(char *buf){ sprintf(buf, "min.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_C_F(char *buf){ sprintf(buf, "c.f.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_EQ(char *buf){ sprintf(buf, "c.eq.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LT(char *buf){ sprintf(buf, "c.lt.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LE(char *buf){ sprintf(buf, "c.le.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_S(char *buf){ sprintf(buf, "cvt.s.w\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf){ sprintf(buf, "qmfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CFC2(char *buf){ sprintf(buf, "cfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_QMTC2(char *buf){ sprintf(buf, "qmtc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CTC2(char *buf){ sprintf(buf, "ctc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_BC2F(char *buf){ sprintf(buf, "bc2f\t%s", offset_decode()); } +void P_BC2T(char *buf){ sprintf(buf, "bc2t\t%s", offset_decode()); } +void P_BC2FL(char *buf){ sprintf(buf, "bc2fl\t%s", offset_decode()); } +void P_BC2TL(char *buf){ sprintf(buf, "bc2tl\t%s", offset_decode()); } +//******************************SPECIAL 1 VUO TABLE**************************************** +#define _X ((cpuRegs.code>>24) & 1) +#define _Y ((cpuRegs.code>>23) & 1) +#define _Z ((cpuRegs.code>>22) & 1) +#define _W ((cpuRegs.code>>21) & 1) + +const char *dest_string(void) +{ + static char str[5]; + int i; + i = 0; + if(_X) str[i++] = 'x'; + if(_Y) str[i++] = 'y'; + if(_Z) str[i++] = 'z'; + if(_W) str[i++] = 'w'; + str[i++] = 0; + return (const char *)str; +} + +char dest_fsf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>21)&3]; +} + +char dest_ftf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>23)&3]; +} + +void P_VADDx(char *buf){sprintf(buf, "vaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDy(char *buf){sprintf(buf, "vaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDz(char *buf){sprintf(buf, "vaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDw(char *buf){sprintf(buf, "vaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBx(char *buf){sprintf(buf, "vsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBy(char *buf){sprintf(buf, "vsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBz(char *buf){sprintf(buf, "vsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBw(char *buf){sprintf(buf, "vsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDx(char *buf){sprintf(buf, "vmaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDy(char *buf){sprintf(buf, "vmaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDz(char *buf){sprintf(buf, "vmaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDw(char *buf){sprintf(buf, "vmaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBx(char *buf){sprintf(buf, "vmsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBy(char *buf){sprintf(buf, "vmsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBz(char *buf){sprintf(buf, "vmsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBw(char *buf){sprintf(buf, "vmsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXx(char *buf){sprintf(buf, "vmaxx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXy(char *buf){sprintf(buf, "vmaxy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXz(char *buf){sprintf(buf, "vmaxz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXw(char *buf){sprintf(buf, "vmaxw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIx(char *buf){sprintf(buf, "vminix.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIy(char *buf){sprintf(buf, "vminiy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); ;} +void P_VMINIz(char *buf){sprintf(buf, "vminiz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIw(char *buf){sprintf(buf, "vminiw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULx(char *buf){sprintf(buf,"vmulx.%s %s,%s,%sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULy(char *buf){sprintf(buf,"vmuly.%s %s,%s,%sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULz(char *buf){sprintf(buf,"vmulz.%s %s,%s,%sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULw(char *buf){sprintf(buf,"vmulw.%s %s,%s,%sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULq(char *buf){sprintf(buf,"vmulq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMAXi(char *buf){sprintf(buf,"vmaxi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMULi(char *buf){sprintf(buf,"vmuli.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMINIi(char *buf){sprintf(buf,"vminii.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDq(char *buf){sprintf(buf,"vaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDq(char *buf){sprintf(buf,"vmaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDi(char *buf){sprintf(buf,"vaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDi(char *buf){sprintf(buf,"vmaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUBq(char *buf){sprintf(buf,"vsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBq(char *buf){sprintf(buf,"vmsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUbi(char *buf){sprintf(buf,"vsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBi(char *buf){sprintf(buf,"vmsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADD(char *buf){sprintf(buf, "vadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADD(char *buf){sprintf(buf, "vmadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMUL(char *buf){sprintf(buf, "vmul.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAX(char *buf){sprintf(buf, "vmax.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUB(char *buf){sprintf(buf, "vsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUB(char *buf){sprintf(buf, "vmsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMSUB(char *buf){sprintf(buf, "vopmsub.xyz %s, %s, %s", COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINI(char *buf){sprintf(buf, "vmini.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VIADD(char *buf){strcpy(buf,"viadd");} +void P_VISUB(char *buf){strcpy(buf,"visub");} +void P_VIADDI(char *buf){strcpy(buf,"viaddi");} +void P_VIAND(char *buf){strcpy(buf,"viand");} +void P_VIOR(char *buf){strcpy(buf,"vior");} +void P_VCALLMS(char *buf){strcpy(buf,"vcallms");} +void P_CALLMSR(char *buf){strcpy(buf,"callmsr");} +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf){sprintf(buf,"vaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAy(char *buf){sprintf(buf,"vadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAz(char *buf){sprintf(buf,"vaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAw(char *buf){sprintf(buf,"vaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAx(char *buf){sprintf(buf,"vsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAy(char *buf){sprintf(buf,"vsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAz(char *buf){sprintf(buf,"vsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAw(char *buf){sprintf(buf,"vsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAx(char *buf){sprintf(buf,"vmaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAy(char *buf){sprintf(buf,"vmadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAz(char *buf){sprintf(buf,"vmaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAw(char *buf){sprintf(buf,"vmaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAx(char *buf){sprintf(buf,"vmsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAy(char *buf){sprintf(buf,"vmsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAz(char *buf){sprintf(buf,"vmsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAw(char *buf){sprintf(buf,"vmsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VITOF0(char *buf){sprintf(buf, "vitof0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF4(char *buf){sprintf(buf, "vitof4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF12(char *buf){sprintf(buf, "vitof12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF15(char *buf){sprintf(buf, "vitof15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI0(char *buf) {sprintf(buf, "vftoi0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI4(char *buf) {sprintf(buf, "vftoi4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI12(char *buf){sprintf(buf, "vftoi12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI15(char *buf){sprintf(buf, "vftoi15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VMULAx(char *buf){sprintf(buf,"vmulax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAy(char *buf){sprintf(buf,"vmulay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAz(char *buf){sprintf(buf,"vmulaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAw(char *buf){sprintf(buf,"vmulaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAq(char *buf){sprintf(buf,"vmulaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VABS(char *buf){sprintf(buf, "vabs.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]);} +void P_VMULAi(char *buf){sprintf(buf,"vmulaq.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VCLIPw(char *buf){sprintf(buf,"vclip %sxyz, %sw", COP2_REG_FP[DECODE_FS], COP2_REG_FP[DECODE_FT]);} +void P_VADDAq(char *buf){sprintf(buf,"vaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAq(char *buf){sprintf(buf,"vmaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDAi(char *buf){sprintf(buf,"vaddai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAi(char *buf){sprintf(buf,"vmaddai.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAq(char *buf){sprintf(buf,"vsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAq(char *buf){sprintf(buf,"vmsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAi(char *buf){sprintf(buf,"vsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAi(char *buf){sprintf(buf,"vmsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDA(char *buf){sprintf(buf,"vadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDA(char *buf){sprintf(buf,"vmadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULA(char *buf){sprintf(buf,"vmula.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBA(char *buf){sprintf(buf,"vsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBA(char *buf){sprintf(buf,"vmsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMULA(char *buf){sprintf(buf,"vopmula.xyz %sxyz, %sxyz" ,COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VNOP(char *buf){strcpy(buf,"vnop");} +void P_VMONE(char *buf){sprintf(buf,"vmove.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VMR32(char *buf){sprintf(buf,"vmr32.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VLQI(char *buf){sprintf(buf,"vlqi %s%s, (%s++)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQI(char *buf){sprintf(buf,"vsqi %s%s, (%s++)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VLQD(char *buf){sprintf(buf,"vlqd %s%s, (--%s)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQD(char *buf){sprintf(buf,"vsqd %s%s, (--%s)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VDIV(char *buf){sprintf(buf,"vdiv Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VSQRT(char *buf){sprintf(buf,"vsqrt Q, %s%c", COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VRSQRT(char *buf){sprintf(buf,"vrsqrt Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VWAITQ(char *buf){sprintf(buf,"vwaitq");} +void P_VMTIR(char *buf){sprintf(buf,"vmtir %s, %s%c", COP2_REG_CTL[DECODE_FT], COP2_REG_FP[DECODE_FS], dest_fsf());} +void P_VMFIR(char *buf){sprintf(buf,"vmfir %s%c, %s", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VILWR(char *buf){sprintf(buf,"vilwr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VISWR(char *buf){sprintf(buf,"viswr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRNEXT(char *buf){sprintf(buf,"vrnext %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRGET(char *buf){sprintf(buf,"vrget %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRINIT(char *buf){sprintf(buf,"vrinit R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRXOR(char *buf){sprintf(buf,"vrxor R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +//************************************END OF SPECIAL2 VUO TABLE**************************** diff --git a/DebugTools/DisVU0Micro.c b/DebugTools/DisVU0Micro.c new file mode 100644 index 0000000000..f5d36dcc71 --- /dev/null +++ b/DebugTools/DisVU0Micro.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dNameU(i) { char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); sprintf(ostr, "%s %-7s,", ostr, op); } + + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) +#define dImm5() sprintf(ostr, "%s %d,", ostr, (code >> 6) & 0x1f) +#define dImm11() sprintf(ostr, "%s %d,", ostr, code & 0x7ff) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" +#include "VU.h" + +_disVUOpcodes(VU0); +_disVUTables(VU0); + diff --git a/DebugTools/DisVU1Micro.c b/DebugTools/DisVU1Micro.c new file mode 100644 index 0000000000..fec3f2746e --- /dev/null +++ b/DebugTools/DisVU1Micro.c @@ -0,0 +1,123 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VUmicro.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + if( !CHECK_VU1REC ) sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + else ostr[0] = 0; \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-12s", ostr, i); \ + +#define dNameU(i) { \ + char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); \ + sprintf(ostr, "%s %-12s", ostr, op); \ +} + +#define dCP2128f(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%8.8x) z=%f (%8.8x) y=%f (%8.8xl) x=%f (%8.8x) (%s),", ostr, VU1.VF[i].f.w, VU1.VF[i].UL[3], VU1.VF[i].f.z, VU1.VF[i].UL[2], VU1.VF[i].f.y, VU1.VF[i].UL[1], VU1.VF[i].f.x, VU1.VF[i].UL[0], disRNameCP2f[i]); \ +} \ + +#define dCP232x(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s x=%f (%s),", ostr, VU1.VF[i].f.x, disRNameCP2f[i]); \ +} \ + +#define dCP232y(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s y=%f (%s),", ostr, VU1.VF[i].f.y, disRNameCP2f[i]); \ +} \ + +#define dCP232z(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s z=%f (%s),", ostr, VU1.VF[i].f.z, disRNameCP2f[i]); \ +} + +#define dCP232w(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%s),", ostr, VU1.VF[i].f.w, disRNameCP2f[i]); \ +} + +#define dCP2ACCf() { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s ACC,", ostr); \ + else sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU1.ACC.f.w, VU1.ACC.f.z, VU1.ACC.f.y, VU1.ACC.f.x); \ +} \ + +#define dCP232i(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %8.8x (%s),", ostr, VU1.VI[i].UL, disRNameCP2i[i]); \ +} + +#define dCP232iF(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %f (%s),", ostr, VU1.VI[i].F, disRNameCP2i[i]); \ +} + +#define dCP232f(i, j) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s%s,", ostr, disRNameCP2f[i], CP2VFnames[j]); \ + else sprintf(ostr, "%s %s=%f (%s),", ostr, CP2VFnames[j], VU1.VF[i].F[j], disRNameCP2f[i]); \ +} + +#define dImm5() sprintf(ostr, "%s %d,", ostr, (s16)((code >> 6) & 0x10 ? 0xfff0 | ((code >> 6) & 0xf) : (code >> 6) & 0xf)) +#define dImm11() sprintf(ostr, "%s %d,", ostr, (s16)(code & 0x400 ? 0xfc00 | (code & 0x3ff) : code & 0x3ff)) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" + +_disVUOpcodes(VU1); +_disVUTables(VU1); + diff --git a/DebugTools/DisVUmicro.h b/DebugTools/DisVUmicro.h new file mode 100644 index 0000000000..7915cde3e7 --- /dev/null +++ b/DebugTools/DisVUmicro.h @@ -0,0 +1,209 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUTables(VU) \ + \ +/****************/ \ +/* LOWER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##LowerOP_T3_00_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MOVE , dis##VU##MI_LQI , dis##VU##MI_DIV , dis##VU##MI_MTIR, \ + dis##VU##MI_RNEXT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_MFP , dis##VU##MI_XTOP , dis##VU##MI_XGKICK, \ + dis##VU##MI_ESADD , dis##VU##MI_EATANxy, dis##VU##MI_ESQRT, dis##VU##MI_ESIN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_01_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MR32 , dis##VU##MI_SQI , dis##VU##MI_SQRT , dis##VU##MI_MFIR, \ + dis##VU##MI_RGET , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , dis##VU##MI_XITOP, disNULL , \ + dis##VU##MI_ERSADD, dis##VU##MI_EATANxz, dis##VU##MI_ERSQRT, dis##VU##MI_EATAN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_10_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_LQD , dis##VU##MI_RSQRT, dis##VU##MI_ILWR, \ + dis##VU##MI_RINIT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ELENG , dis##VU##MI_ESUM , dis##VU##MI_ERCPR, dis##VU##MI_EEXP, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_11_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_SQD , dis##VU##MI_WAITQ, dis##VU##MI_ISWR, \ + dis##VU##MI_RXOR , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ERLENG, disNULL , dis##VU##MI_WAITP, disNULL , \ +}; \ + \ +MakeDisF(dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_00_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_01_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_10_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_11, dis##VU##LowerOP_T3_11_OPCODE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##LowerOP_OPCODE[64] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x20 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_IADD , dis##VU##MI_ISUB , dis##VU##MI_IADDI, disNULL , /* 0x30 */ \ + dis##VU##MI_IAND , dis##VU##MI_IOR , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_11, \ +}; \ + \ +MakeDisF(dis##VU##LowerOP, dis##VU##LowerOP_OPCODE[code & 0x3f] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroL[] = { \ + dis##VU##MI_LQ , dis##VU##MI_SQ , disNULL , disNULL, \ + dis##VU##MI_ILW , dis##VU##MI_ISW , disNULL , disNULL, \ + dis##VU##MI_IADDIU, dis##VU##MI_ISUBIU, disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##MI_FCEQ , dis##VU##MI_FCSET , dis##VU##MI_FCAND, dis##VU##MI_FCOR, /* 0x10 */ \ + dis##VU##MI_FSEQ , dis##VU##MI_FSSET , dis##VU##MI_FSAND, dis##VU##MI_FSOR, \ + dis##VU##MI_FMEQ , disNULL , dis##VU##MI_FMAND, dis##VU##MI_FMOR, \ + dis##VU##MI_FCGET , disNULL , disNULL , disNULL, \ + dis##VU##MI_B , dis##VU##MI_BAL , disNULL , disNULL, /* 0x20 */ \ + dis##VU##MI_JR , dis##VU##MI_JALR , disNULL , disNULL, \ + dis##VU##MI_IBEQ , dis##VU##MI_IBNE , disNULL , disNULL, \ + dis##VU##MI_IBLTZ , dis##VU##MI_IBGTZ , dis##VU##MI_IBLEZ, dis##VU##MI_IBGEZ, \ + disNULL , disNULL , disNULL , disNULL, /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##LowerOP , disNULL , disNULL , disNULL, /* 0x40*/ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x50 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x60 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x70 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroLF, dis##VU##MicroL[code >> 25] DisFInterfaceN) \ + \ + \ +/****************/ \ +/* UPPER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##_UPPER_FD_00_TABLE[32] = { \ + dis##VU##MI_ADDAx, dis##VU##MI_SUBx , dis##VU##MI_MADDAx, dis##VU##MI_MSUBAx, \ + dis##VU##MI_ITOF0, dis##VU##MI_FTOI0, dis##VU##MI_MULAx , dis##VU##MI_MULAq , \ + dis##VU##MI_ADDAq, dis##VU##MI_SUBAq, dis##VU##MI_ADDA , dis##VU##MI_SUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_01_TABLE[32] = { \ + dis##VU##MI_ADDAy , dis##VU##MI_SUBy , dis##VU##MI_MADDAy, dis##VU##MI_MSUBAy, \ + dis##VU##MI_ITOF4 , dis##VU##MI_FTOI4 , dis##VU##MI_MULAy , dis##VU##MI_ABS , \ + dis##VU##MI_MADDAq, dis##VU##MI_MSUBAq, dis##VU##MI_MADDA , dis##VU##MI_MSUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_10_TABLE[32] = { \ + dis##VU##MI_ADDAz , dis##VU##MI_SUBz , dis##VU##MI_MADDAz, dis##VU##MI_MSUBAz, \ + dis##VU##MI_ITOF12, dis##VU##MI_FTOI12, dis##VU##MI_MULAz , dis##VU##MI_MULAi , \ + dis##VU##MI_MADDAi, dis##VU##MI_SUBAi , dis##VU##MI_MULA , dis##VU##MI_OPMULA, \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_11_TABLE[32] = { \ + dis##VU##MI_ADDAw , dis##VU##MI_SUBw , dis##VU##MI_MADDAw, dis##VU##MI_MSUBAw, \ + dis##VU##MI_ITOF15, dis##VU##MI_FTOI15, dis##VU##MI_MULAw , dis##VU##MI_CLIP , \ + dis##VU##MI_MADDAi, dis##VU##MI_MSUBAi, disNULL , dis##VU##MI_NOP , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +MakeDisF(dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_00_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_01_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_10_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_11, dis##VU##_UPPER_FD_11_TABLE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroU[] = { \ + dis##VU##MI_ADDx , dis##VU##MI_ADDy , dis##VU##MI_ADDz , dis##VU##MI_ADDw, \ + dis##VU##MI_SUBx , dis##VU##MI_SUBy , dis##VU##MI_SUBz , dis##VU##MI_SUBw, \ + dis##VU##MI_MADDx , dis##VU##MI_MADDy , dis##VU##MI_MADDz , dis##VU##MI_MADDw, \ + dis##VU##MI_MSUBx , dis##VU##MI_MSUBy , dis##VU##MI_MSUBz , dis##VU##MI_MSUBw, \ + dis##VU##MI_MAXx , dis##VU##MI_MAXy , dis##VU##MI_MAXz , dis##VU##MI_MAXw, /* 0x10 */ \ + dis##VU##MI_MINIx , dis##VU##MI_MINIy , dis##VU##MI_MINIz , dis##VU##MI_MINIw, \ + dis##VU##MI_MULx , dis##VU##MI_MULy , dis##VU##MI_MULz , dis##VU##MI_MULw, \ + dis##VU##MI_MULq , dis##VU##MI_MAXi , dis##VU##MI_MULi , dis##VU##MI_MINIi, \ + dis##VU##MI_ADDq , dis##VU##MI_MADDq , dis##VU##MI_ADDi , dis##VU##MI_MADDi, /* 0x20 */ \ + dis##VU##MI_SUBq , dis##VU##MI_MSUBq , dis##VU##MI_SUBi , dis##VU##MI_MSUBi, \ + dis##VU##MI_ADD , dis##VU##MI_MADD , dis##VU##MI_MUL , dis##VU##MI_MAX, \ + dis##VU##MI_SUB , dis##VU##MI_MSUB , dis##VU##MI_OPMSUB, dis##VU##MI_MINI, \ + disNULL , disNULL , disNULL , disNULL , /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_11, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroUF, dis##VU##MicroU[code & 0x3f] DisFInterfaceN) \ + diff --git a/DebugTools/DisVUops.h b/DebugTools/DisVUops.h new file mode 100644 index 0000000000..40cf978292 --- /dev/null +++ b/DebugTools/DisVUops.h @@ -0,0 +1,197 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUOpcodes(VU) \ + \ +/*****************/ \ +/* LOWER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_DIV, dName("DIV"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_SQRT, dName("SQRT"); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_RSQRT, dName("RSQRT"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_IADDI, dName("IADDI"); dCP232i(_Ft_); dCP232i(_Fs_); dImm5();) \ +MakeDisF(dis##VU##MI_IADDIU, dName("IADDIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_IADD, dName("IADD"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IAND, dName("IAND"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IOR, dName("IOR"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUB, dName("ISUB"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUBIU, dName("ISUBIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_MOVE, if (_Fs_ == 0 && _Ft_ == 0) { dNameU("NOP"); } else { dNameU("MOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_); }) \ +MakeDisF(dis##VU##MI_MFIR, dNameU("MFIR"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_MTIR, dNameU("MTIR"); dCP232i(_Ft_); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_MR32, dNameU("MR32"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_LQ, dNameU("LQ"); dCP2128f(_Ft_); dCP232i(_Fs_); dImm11();) \ +MakeDisF(dis##VU##MI_LQD, dNameU("LQD"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LQI, dNameU("LQI"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_SQ, dNameU("SQ"); dCP2128f(_Fs_); dCP232i(_Ft_); dImm11(); ) \ +MakeDisF(dis##VU##MI_SQD, dNameU("SQD"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_SQI, dNameU("SQI"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ILW, dNameU("ILW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISW, dNameU("ISW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ILWR, dNameU("ILWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISWR, dNameU("ISWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LOI, dName("LOI"); ) \ +MakeDisF(dis##VU##MI_RINIT, dNameU("RINIT"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_RGET, dNameU("RGET"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RNEXT, dNameU("RNEXT"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RXOR, dNameU("RXOR"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_WAITQ, dName("WAITQ"); ) \ +MakeDisF(dis##VU##MI_FSAND, dName("FSAND"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff); ) \ +MakeDisF(dis##VU##MI_FSEQ, dName("FSEQ"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSOR, dName("FSOR"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSSET, dName("FSSET"); dCP232i(REG_STATUS_FLAG);) \ +MakeDisF(dis##VU##MI_FMAND, dName("FMAND"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMEQ, dName("FMEQ"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMOR, dName("FMOR"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FCAND, dName("FCAND"); dCP232i(1); sprintf(ostr, "%s %8.8x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCEQ, dName("FCEQ"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCOR, dName("FCOR"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCSET, dName("FCSET"); dCP232i(REG_CLIP_FLAG); sprintf(ostr, "%s %.6x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCGET, dName("FCGET"); dCP232i(_Ft_); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_IBEQ, dName("IBEQ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGEZ, dName("IBEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGTZ, dName("IBGTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLEZ, dName("IBLEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLTZ, dName("IBLTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBNE, dName("IBNE"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_B, dName("B"); dImm11();) \ +MakeDisF(dis##VU##MI_BAL, dName("BAL"); dImm11(); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_JR, dName("JR"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_JALR, dName("JALR"); dCP232i(_Ft_); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_MFP, dNameU("MFP"); dCP2128f(_Ft_); dCP232i(REG_P);) \ +MakeDisF(dis##VU##MI_WAITP, dName("WAITP"); ) \ +MakeDisF(dis##VU##MI_ESADD, dName("ESADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ERSADD, dName("ERSADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ELENG, dName("ELENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERLENG, dName("ERLENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_EATANxy, dName("EATANxy"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_EATANxz, dName("EATANxz"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ESUM, dName("ESUM"); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERCPR, dName("ERCPR"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESQRT, dName("ESQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ERSQRT, dName("ERSQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESIN, dName("ESIN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EATAN, dName("EATAN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EEXP, dName("EEXP"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_XITOP, dName("XITOP"); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_XGKICK, dName("XGKICK"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_XTOP, dName("XTOP"); dCP232i(_Ft_);) \ + \ + \ +/*****************/ \ +/* UPPER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_ABS, dNameU("ABS"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ADD, dNameU("ADD"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDi, dNameU("ADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDq, dNameU("ADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDx, dNameU("ADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDy, dNameU("ADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDz, dNameU("ADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDw, dNameU("ADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDA, dNameU("ADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAi, dNameU("ADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDAq, dNameU("ADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDAx, dNameU("ADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAy, dNameU("ADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAz, dNameU("ADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAw, dNameU("ADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUB, dNameU("SUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBi, dNameU("SUBi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBq, dNameU("SUBq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBx, dNameU("SUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBy, dNameU("SUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBz, dNameU("SUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBw, dNameU("SUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBA, dNameU("SUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAi, dNameU("SUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBAq, dNameU("SUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBAx, dNameU("SUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAy, dNameU("SUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAz, dNameU("SUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAw, dNameU("SUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MUL, dNameU("MUL"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULi, dNameU("MULi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULq, dNameU("MULq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULx, dNameU("MULx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULy, dNameU("MULy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULz, dNameU("MULz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULw, dNameU("MULw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MULA, dNameU("MULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAi, dNameU("MULAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULAq, dNameU("MULAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULAx, dNameU("MULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAy, dNameU("MULAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAz, dNameU("MULAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAw, dNameU("MULAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADD, dNameU("MADD"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDi, dNameU("MADDi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDq, dNameU("MADDq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDx, dNameU("MADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDy, dNameU("MADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDz, dNameU("MADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDw, dNameU("MADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDA, dNameU("MADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAi, dNameU("MADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDAq, dNameU("MADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDAx, dNameU("MADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAy, dNameU("MADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAz, dNameU("MADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAw, dNameU("MADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUB, dNameU("MSUB"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBi, dNameU("MSUBi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBq, dNameU("MSUBq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBx, dNameU("MSUBx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBy, dNameU("MSUBy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBz, dNameU("MSUBz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBw, dNameU("MSUBw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBA, dNameU("MSUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAi, dNameU("MSUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBAq, dNameU("MSUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBAx, dNameU("MSUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAy, dNameU("MSUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAz, dNameU("MSUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAw, dNameU("MSUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MAX, dNameU("MAX"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXi, dNameU("MAXi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MAXx, dNameU("MAXx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXy, dNameU("MAXy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXz, dNameU("MAXz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXw, dNameU("MAXw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MINI, dNameU("MINI"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIi, dNameU("MINIi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MINIx, dNameU("MINIx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIy, dNameU("MINIy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIz, dNameU("MINIz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIw, dNameU("MINIw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMULA, dNameU("OPMULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMSUB, dNameU("OPMSUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_NOP, dName("NOP");) \ +MakeDisF(dis##VU##MI_FTOI0, dNameU("FTOI0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI4, dNameU("FTOI4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI12, dNameU("FTOI12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI15, dNameU("FTOI15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF0, dNameU("ITOF0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF4, dNameU("ITOF4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF12, dNameU("ITOF12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF15, dNameU("ITOF15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_CLIP, dNameU("CLIP"); dCP2128f(_Fs_); dCP232w(_Ft_);) \ + diff --git a/DebugTools/cpuopsDebug.c b/DebugTools/cpuopsDebug.c new file mode 100644 index 0000000000..99d6baf6c0 --- /dev/null +++ b/DebugTools/cpuopsDebug.c @@ -0,0 +1,1063 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "cpuopsDebug.h" + +void UpdateR5900op() +{ + FILE *fp; + fp=fopen("cpuops.txt", "wt"); + fprintf(fp, "------------\n"); + fprintf(fp, "--R5900ops--\n"); + fprintf(fp, "------------\n"); + if(L_ADD>0) fprintf(fp, "Add %d\n", L_ADD); + if(L_ADDI>0) fprintf(fp, "Addi %d\n", L_ADDI); + if(L_ADDIU>0) fprintf(fp, "Addiu %d\n", L_ADDIU); + if(L_ADDU>0) fprintf(fp, "Addu %d\n", L_ADDU); + if(L_AND>0) fprintf(fp, "And %d\n", L_AND); + if(L_ANDI>0) fprintf(fp, "Andi %d\n", L_ANDI); + if(L_BEQ>0) fprintf(fp, "Beq %d\n", L_BEQ); + if(L_BEQL>0) fprintf(fp, "Beql %d\n", L_BEQL); + if(L_BGEZ>0) fprintf(fp, "Bgez %d\n", L_BGEZ); + if(L_BGEZAL>0) fprintf(fp, "Bgezal %d\n", L_BGEZAL); + if(L_BGEZALL>0) fprintf(fp, "Bgezall %d\n", L_BGEZALL); + if(L_BGEZL>0) fprintf(fp, "Bgezl %d\n", L_BGEZL); + if( L_BGTZ>0) fprintf(fp, "Bgtz %d\n", L_BGTZ); + if( L_BGTZL>0) fprintf(fp, "Bgtzl %d\n", L_BGTZL); + if(L_BLEZ>0) fprintf(fp, "Blez %d\n", L_BLEZ); + if(L_BLEZL>0) fprintf(fp, "blezl %d\n", L_BLEZL); + if(L_BLTZ>0) fprintf(fp, "bltz %d\n", L_BLTZ); + if(L_BLTZAL>0) fprintf(fp, "bltzal %d\n", L_BLTZAL); + if(L_BLTZALL>0) fprintf(fp, "bltzall %d\n", L_BLTZALL); + if(L_BLTZL>0) fprintf(fp, "bltzl %d\n", L_BLTZL); + if(L_BNE>0) fprintf(fp, "bne %d\n", L_BNE); + if(L_BNEL>0) fprintf(fp, "bnel %d\n", L_BNEL); + if(L_BREAK>0) fprintf(fp, "break %d\n", L_BREAK); + if(L_CACHE>0) fprintf(fp, "cache %d\n", L_CACHE); + if(L_DADD>0) fprintf(fp, "dadd %d\n", L_DADD); + if(L_DADDI>0) fprintf(fp, "daddi %d\n", L_DADDI); + if(L_DADDIU>0) fprintf(fp, "daddiu %d\n", L_DADDIU); + if(L_DADDU>0) fprintf(fp, "daddu %d\n", L_DADDU); + if(L_DIV>0) fprintf(fp, "div %d\n", L_DIV); + if(L_DIVU>0) fprintf(fp, "divu %d\n", L_DIVU); + if(L_DSLL>0) fprintf(fp, "dsll %d\n", L_DSLL); + if(L_DSLL32>0) fprintf(fp, "dsll32 %d\n", L_DSLL32); + if(L_DSLLV>0) fprintf(fp, "dsllv %d\n", L_DSLLV); + if(L_DSRA>0) fprintf(fp, "dsra %d\n", L_DSRA); + if(L_DSRA32>0) fprintf(fp, "dsra32 %d\n", L_DSRA32); + if(L_DSRAV>0) fprintf(fp, "dsrav %d\n", L_DSRAV); + if(L_DSRL>0) fprintf(fp, "dsrl %d\n", L_DSRL); + if(L_DSRL32>0) fprintf(fp, "dsr32 %d\n", L_DSRL32); + if(L_DSRLV>0) fprintf(fp, "dsrlv %d\n", L_DSRLV); + if(L_DSUB>0) fprintf(fp, "dsub %d\n", L_DSUB); + if(L_DSUBU>0) fprintf(fp, "dsubu %d\n", L_DSUBU); + if(L_J>0) fprintf(fp, "j %d\n", L_J); + if(L_JAL>0) fprintf(fp, "jal %d\n", L_JAL); + if(L_JALR>0) fprintf(fp, "jalr %d\n", L_JALR); + if(L_JR>0) fprintf(fp, "jr %d\n", L_JR); + if(L_LB>0) fprintf(fp, "lb %d\n", L_LB); + if(L_LBU>0) fprintf(fp, "lbu %d\n", L_LBU); + if(L_LD>0) fprintf(fp, "ld %d\n", L_LD); + if(L_LDL>0) fprintf(fp, "ldl %d\n", L_LDL); + if(L_LDR>0) fprintf(fp, "ldr %d\n", L_LDR); + if(L_LH>0) fprintf(fp, "lh %d\n", L_LH); + if(L_LHU>0) fprintf(fp, "lhu %d\n", L_LHU); + if(L_LQ>0) fprintf(fp, "lq %d\n", L_LQ); + if(L_LUI>0) fprintf(fp, "lui %d\n", L_LUI); + if(L_LW>0) fprintf(fp, "lw %d\n", L_LW); + if(L_LWL>0) fprintf(fp, "lwl %d\n", L_LWL); + if(L_LWR>0) fprintf(fp, "lwr %d\n", L_LWR); + if(L_LWU>0) fprintf(fp, "lwu %d\n", L_LWU); + if(L_MFHI>0) fprintf(fp, "mfhi %d\n", L_MFHI); + if(L_MFLO>0) fprintf(fp, "mflo %d\n", L_MFLO); + if(L_MFSA>0) fprintf(fp, "mfsa %d\n", L_MFSA); + if(L_MOVN>0) fprintf(fp, "movn %d\n", L_MOVN); + if(L_MOVZ>0) fprintf(fp, "movz %d\n", L_MOVZ); + if(L_MTHI>0) fprintf(fp, "mthi %d\n", L_MTHI); + if(L_MTLO>0) fprintf(fp, "mtlo %d\n", L_MTLO); + if(L_MTSA>0) fprintf(fp, "mtsa %d\n", L_MTSA); + if(L_MTSAB>0) fprintf(fp, "mtsab %d\n", L_MTSAB); + if(L_MTSAH>0) fprintf(fp, "mtsah %d\n", L_MTSAH); + if(L_MULT>0) fprintf(fp, "mult %d\n", L_MULT); + if(L_MULTU>0) fprintf(fp, "multu %d\n", L_MULTU); + if(L_NOR>0) fprintf(fp, "nor %d\n", L_NOR); + if(L_OR>0) fprintf(fp, "or %d\n", L_OR); + if(L_ORI>0) fprintf(fp, "ori %d\n", L_ORI); + if(L_PREF>0) fprintf(fp, "pref %d\n", L_PREF); + if(L_SB>0) fprintf(fp, "sb %d\n", L_SB); + if(L_SD>0) fprintf(fp, "sd %d\n", L_SD); + if(L_SDL>0) fprintf(fp, "sdl %d\n", L_SDL); + if(L_SDR>0) fprintf(fp, "sdr %d\n", L_SDR); + if(L_SH>0) fprintf(fp, "sh %d\n", L_SH); + if(L_SLL>0) fprintf(fp, "sll %d\n", L_SLL); + if(L_SLLV>0) fprintf(fp, "sllv %d\n", L_SLLV); + if(L_SLT>0) fprintf(fp, "slt %d\n", L_SLT); + if(L_SLTI>0) fprintf(fp, "slti %d\n", L_SLTI); + if(L_SLTIU>0) fprintf(fp, "sltiu %d\n", L_SLTIU); + if(L_SLTU>0) fprintf(fp, "sltu %d\n", L_SLTU); + if(L_SQ>0) fprintf(fp, "sq %d\n", L_SQ); + if(L_SRA>0) fprintf(fp, "sra %d\n", L_SRA); + if(L_SRAV>0) fprintf(fp, "srav %d\n", L_SRAV); + if(L_SRL>0) fprintf(fp, "srl %d\n", L_SRL); + if(L_SRLV>0) fprintf(fp, "srlv %d\n", L_SRLV); + if(L_SUB>0) fprintf(fp, "sub %d\n", L_SUB); + if(L_SUBU>0) fprintf(fp, "subu %d\n", L_SUBU); + if(L_SW>0) fprintf(fp, "sw %d\n", L_SW); + if(L_SWL>0) fprintf(fp, "swl %d\n", L_SWL); + if(L_SWR>0) fprintf(fp, "swr %d\n", L_SWR); + if(L_SYNC>0) fprintf(fp, "sync %d\n", L_SYNC); + if(L_SYSCALL>0) fprintf(fp, "syscall %d\n", L_SYSCALL); + if(L_TEQ>0) fprintf(fp, "teq %d\n", L_TEQ); + if(L_TEQI>0) fprintf(fp, "teqi %d\n", L_TEQI); + if(L_TGE>0) fprintf(fp, "tge %d\n", L_TGE); + if(L_TGEI>0) fprintf(fp, "tgei %d\n", L_TGEI); + if(L_TGEIU>0) fprintf(fp, "tgeiu %d\n", L_TGEIU); + if(L_TGEU>0) fprintf(fp, "tgeu %d\n", L_TGEU); + if(L_TLT>0) fprintf(fp, "tlt %d\n", L_TLT); + if(L_TLTI>0) fprintf(fp, "tlti %d\n", L_TLTI); + if(L_TLTIU>0) fprintf(fp, "tltiu %d\n", L_TLTIU); + if(L_TLTU>0) fprintf(fp, "tltu %d\n", L_TLTU); + if(L_TNE>0) fprintf(fp, "tne %d\n", L_TNE); + if(L_TNEI>0) fprintf(fp, "tnei %d\n", L_TNEI); + if(L_XOR>0) fprintf(fp, "xor %d\n", L_XOR); + if(L_XORI>0) fprintf(fp, "xori %d\n", L_XORI); + fprintf(fp, "------------\n"); + fprintf(fp, "--MMI ops--\n"); + fprintf(fp, "------------\n"); + if(L_DIV1>0) fprintf(fp, "div1 %d\n", L_DIV1); + if(L_DIVU1>0) fprintf(fp, "divu1 %d\n", L_DIVU1); + if(L_MADD>0) fprintf(fp, "madd %d\n", L_MADD); + if(L_MADD1>0) fprintf(fp, "madd1 %d\n", L_MADD1); + if(L_MADDU>0) fprintf(fp, "maddu %d\n", L_MADDU); + if(L_MADDU1>0) fprintf(fp, "maddu1 %d\n", L_MADDU1); + if(L_MFHI1>0) fprintf(fp, "mfhi1 %d\n", L_MFHI1); + if(L_MFLO1>0) fprintf(fp, "mflo1 %d\n", L_MFLO1); + if(L_MTHI1>0) fprintf(fp, "mthi1 %d\n", L_MTHI1); + if(L_MTLO1>0) fprintf(fp, "mtlo1 %d\n", L_MTLO1); + if(L_MULT1>0) fprintf(fp, "mult1 %d\n", L_MULT1); + if(L_MULTU1>0) fprintf(fp, "multu1 %d\n", L_MULTU1); + if(L_PABSH>0) fprintf(fp, "pabsh %d\n", L_PABSH); + if(L_PABSW>0) fprintf(fp, "pabsw %d\n", L_PABSW); + if(L_PADDB>0) fprintf(fp, "paddb %d\n", L_PADDB); + if(L_PADDH>0) fprintf(fp, "paddh %d\n", L_PADDH); + if(L_PADDSB>0) fprintf(fp, "paddsb %d\n", L_PADDSB); + if(L_PADDSH>0) fprintf(fp, "paddsh %d\n", L_PADDSH); + if(L_PADDSW>0) fprintf(fp, "paddsw %d\n", L_PADDSW); + if(L_PADDUB>0) fprintf(fp, "paddub %d\n", L_PADDUB); + if(L_PADDUH>0) fprintf(fp, "padduh %d\n", L_PADDUH); + if(L_PADDUW>0) fprintf(fp, "padduw %d\n", L_PADDUW); + if(L_PADDW>0) fprintf(fp, "paddw %d\n", L_PADDW); + if(L_PADSBH>0) fprintf(fp, "padsbh %d\n", L_PADSBH); + if(L_PAND>0) fprintf(fp, "pand %d\n", L_PAND); + if(L_PCEQB>0) fprintf(fp, "pceqb %d\n", L_PCEQB); + if(L_PCEQH>0) fprintf(fp, "pceqh %d\n", L_PCEQH); + if(L_PCEQW>0) fprintf(fp, "pceqw %d\n", L_PCEQW); + if(L_PCGTB>0) fprintf(fp, "pcgtb %d\n", L_PCGTB); + if(L_PCGTH>0) fprintf(fp, "pcgth %d\n", L_PCGTH); + if(L_PCGTW>0) fprintf(fp, "pcgtw %d\n", L_PCGTW); + if(L_PCPYH>0) fprintf(fp, "pcpyh %d\n", L_PCPYH); + if(L_PCPYLD>0) fprintf(fp, "pcpyld %d\n", L_PCPYLD); + if(L_PCPYUD>0) fprintf(fp, "pcpyud %d\n", L_PCPYUD); + if(L_PDIVBW>0) fprintf(fp, "pdivbw %d\n", L_PDIVBW); + if(L_PDIVUW>0) fprintf(fp, "pdivuw %d\n", L_PDIVUW); + if(L_PDIVW>0) fprintf(fp, "pdivw %d\n", L_PDIVW); + if(L_PEXCH>0) fprintf(fp, "pexch %d\n", L_PEXCH); + if(L_PEXCW>0) fprintf(fp, "pexcw %d\n", L_PEXCW); + if(L_PEXEH>0) fprintf(fp, "pexeh %d\n", L_PEXEH); + if(L_PEXEW>0) fprintf(fp, "pexew %d\n", L_PEXEW); + if(L_PEXT5>0) fprintf(fp, "pext5 %d\n", L_PEXT5); + if(L_PEXTLB>0) fprintf(fp, "pextlb %d\n", L_PEXTLB); + if(L_PEXTLH>0) fprintf(fp, "pextlh %d\n", L_PEXTLH); + if(L_PEXTLW>0) fprintf(fp, "pextlw %d\n", L_PEXTLW); + if(L_PEXTUB>0) fprintf(fp, "pextub %d\n", L_PEXTUB); + if(L_PEXTUH>0) fprintf(fp, "pextuh %d\n", L_PEXTUH); + if(L_PEXTUW>0) fprintf(fp, "pextuw %d\n", L_PEXTUW); + if(L_PHMADH>0) fprintf(fp, "phmadh %d\n", L_PHMADH); + if(L_PHMSBH>0) fprintf(fp, "phmsbh %d\n", L_PHMSBH); + if(L_PINTEH>0) fprintf(fp, "pinteh %d\n", L_PINTEH); + if(L_PINTH>0) fprintf(fp, "pinth %d\n", L_PINTH); + if(L_PLZCW>0) fprintf(fp, "plzcw %d\n", L_PLZCW); + if(L_PMADDH>0) fprintf(fp, "pmaddh %d\n", L_PMADDH); + if(L_PMADDUW>0) fprintf(fp, "pmadduw %d\n", L_PMADDUW); + if(L_PMADDW>0) fprintf(fp, "pmaddw %d\n", L_PMADDW); + if(L_PMAXH>0) fprintf(fp, "pmaxh %d\n", L_PMAXH); + if(L_PMAXW>0) fprintf(fp, "pmaxw %d\n", L_PMAXW); + if(L_PMFHI>0) fprintf(fp, "pmfhi %d\n", L_PMFHI); + if(L_PMFHL>0) fprintf(fp, "pmfhl %d\n", L_PMFHL); + if(L_PMFLO>0) fprintf(fp, "pmflo %d\n", L_PMFLO); + if(L_PMINH>0) fprintf(fp, "pminh %d\n", L_PMINH); + if(L_PMINW>0) fprintf(fp, "pminw %d\n", L_PMINW); + if(L_PMSUBH>0) fprintf(fp, "pmsubh %d\n", L_PMSUBH); + if(L_PMSUBW>0) fprintf(fp, "pmsubw %d\n", L_PMSUBW); + if(L_PMTHI>0) fprintf(fp, "pmthi %d\n", L_PMTHI); + if(L_PMTHL>0) fprintf(fp, "pmthl %d\n", L_PMTHL); + if(L_PMTLO>0) fprintf(fp, "pmtlo %d\n", L_PMTLO); + if(L_PMULTH>0) fprintf(fp, "pmulth %d\n", L_PMULTH); + if(L_PMULTUW>0) fprintf(fp, "pmultuw %d\n", L_PMULTUW); + if(L_PMULTW>0) fprintf(fp, "pmultw %d\n", L_PMULTW); + if(L_PNOR>0) fprintf(fp, "pnor %d\n", L_PNOR); + if(L_POR>0) fprintf(fp, "por %d\n", L_POR); + if(L_PPAC5>0) fprintf(fp, "ppac5 %d\n", L_PPAC5); + if(L_PPACB>0) fprintf(fp, "ppacb %d\n", L_PPACB); + if(L_PPACH>0) fprintf(fp, "ppach %d\n", L_PPACH); + if(L_PPACW>0) fprintf(fp, "ppacw %d\n", L_PPACW); + if(L_PREVH>0) fprintf(fp, "prevh %d\n", L_PREVH); + if(L_PROT3W>0) fprintf(fp, "prot3w %d\n", L_PROT3W); + if(L_PSLLH>0) fprintf(fp, "psllh %d\n", L_PSLLH); + if(L_PSLLVW>0) fprintf(fp, "psllvw %d\n", L_PSLLVW); + if(L_PSLLW>0) fprintf(fp, "psllw %d\n", L_PSLLW); + if(L_PSRAH>0) fprintf(fp, "psrah %d\n", L_PSRAH); + if(L_PSRAVW>0) fprintf(fp, "psravw %d\n", L_PSRAVW); + if(L_PSRAW>0) fprintf(fp, "psraw %d\n", L_PSRAW); + if(L_PSRLH>0) fprintf(fp, "psrlh %d\n", L_PSRLH); + if(L_PSRLVW>0) fprintf(fp, "psrlvw %d\n", L_PSRLVW); + if(L_PSRLW>0) fprintf(fp, "psrlw %d\n", L_PSRLW); + if(L_PSUBB>0) fprintf(fp, "psubb %d\n", L_PSUBB); + if(L_PSUBH>0) fprintf(fp, "psubh %d\n", L_PSUBH); + if(L_PSUBSB>0) fprintf(fp, "psubsb %d\n", L_PSUBSB); + if(L_PSUBSH>0) fprintf(fp, "psubsh %d\n", L_PSUBSH); + if(L_PSUBSW>0) fprintf(fp, "psubsw %d\n", L_PSUBSW); + if(L_PSUBUB>0) fprintf(fp, "psubub %d\n", L_PSUBUB); + if(L_PSUBUH>0) fprintf(fp, "psubuh %d\n", L_PSUBUH); + if(L_PSUBUW>0) fprintf(fp, "psubuw %d\n", L_PSUBUW); + if(L_PSUBW>0) fprintf(fp, "psubw %d\n", L_PSUBW); + if(L_PXOR>0) fprintf(fp, "pxor %d\n", L_PXOR); + if(L_QFSRV>0) fprintf(fp, "qfsrv %d\n", L_QFSRV); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP0 ops--\n"); + fprintf(fp, "------------\n"); + if(L_BC0F>0) fprintf(fp, "bc0f %d\n", L_BC0F); + if(L_BC0FL>0) fprintf(fp, "bc0fl %d\n", L_BC0FL); + if(L_BC0T>0) fprintf(fp, "bc0t %d\n", L_BC0T); + if(L_BC0TL>0) fprintf(fp, "bc0tl %d\n", L_BC0TL); + if(L_DI>0) fprintf(fp, "di %d\n", L_DI); + if(L_EI>0) fprintf(fp, "ei %d\n", L_EI); + if(L_ERET>0) fprintf(fp, "eret %d\n", L_ERET); + if(L_MTC0>0) fprintf(fp, "mtc0 %d\n", L_MTC0); + if(L_TLBP>0) fprintf(fp, "tlbp %d\n", L_TLBP); + if(L_TLBR>0) fprintf(fp, "tlbr %d\n", L_TLBR); + if(L_TLBWI>0) fprintf(fp, "tlbwi %d\n", L_TLBWI); + if(L_TLBWR>0) fprintf(fp, "tlbwr %d\n", L_TLBWR); + if(L_MFC0>0) fprintf(fp, "mfc0 %d\n", L_MFC0); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP1 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LWC1>0) fprintf(fp, "lwc1 %d\n", L_LWC1); + if(L_SWC1>0) fprintf(fp, "swc1 %d\n", L_SWC1); + if(L_ABS_S>0) fprintf(fp, "abs_s %d\n", L_ABS_S); + if(L_ADD_S>0) fprintf(fp, "add_s %d\n", L_ADD_S); + if(L_ADDA_S>0) fprintf(fp, "adda_s %d\n", L_ADDA_S); + if(L_BC1F>0) fprintf(fp, "bc1f %d\n", L_BC1F); + if(L_BC1FL>0) fprintf(fp, "bc1fl %d\n", L_BC1FL); + if(L_BC1T>0) fprintf(fp, "bc1t %d\n", L_BC1T); + if(L_BC1TL>0) fprintf(fp, "bc1tl %d\n", L_BC1TL); + if(L_C_EQ>0) fprintf(fp, "c_eq %d\n", L_C_EQ); + if(L_C_F>0) fprintf(fp, "c_f %d\n", L_C_F); + if(L_C_LE>0) fprintf(fp, "c_le %d\n", L_C_LE); + if(L_C_LT>0) fprintf(fp, "c_lt %d\n", L_C_LT); + if(L_CFC1>0) fprintf(fp, "cfc1 %d\n", L_CFC1); + if(L_CTC1>0) fprintf(fp, "ctc1 %d\n", L_CTC1); + if(L_CVT_S>0) fprintf(fp, "cvt_s %d\n", L_CVT_S); + if(L_CVT_W>0) fprintf(fp, "cvt_w %d\n", L_CVT_W); + if(L_DIV_S>0) fprintf(fp, "div_s %d\n", L_DIV_S); + if(L_MADD_S>0) fprintf(fp, "madd_s %d\n", L_MADD_S); + if(L_MADDA_S>0) fprintf(fp, "madda_s %d\n", L_MADDA_S); + if(L_MAX_S>0) fprintf(fp, "max_s %d\n", L_MAX_S); + if(L_MFC1>0) fprintf(fp, "mfc1 %d\n", L_MFC1); + if(L_MIN_S>0) fprintf(fp, "min_s %d\n", L_MIN_S); + if(L_MOV_S>0) fprintf(fp, "mov_s %d\n", L_MOV_S); + if(L_MSUB_S>0) fprintf(fp, "msub_s %d\n", L_MSUB_S); + if(L_MSUBA_S>0) fprintf(fp, "msuba_s %d\n", L_MSUBA_S); + if(L_MTC1>0) fprintf(fp, "mtc1 %d\n", L_MTC1); + if(L_MUL_S>0) fprintf(fp, "mul_s %d\n", L_MUL_S); + if(L_MULA_S>0) fprintf(fp, "mula_s %d\n", L_MULA_S); + if(L_NEG_S>0) fprintf(fp, "neg_s %d\n", L_NEG_S); + if(L_RSQRT_S>0) fprintf(fp, "rsqrt_s %d\n", L_RSQRT_S); + if(L_SQRT_S>0) fprintf(fp, "sqrt_s %d\n", L_SQRT_S); + if(L_SUB_S>0) fprintf(fp, "sub_s %d\n", L_SUB_S); + if(L_SUBA_S>0) fprintf(fp, "suba_s %d\n", L_SUBA_S); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP2 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LQC2>0) fprintf(fp, "lqc2 %d\n", L_LQC2); + if(L_SQC2>0) fprintf(fp, "sqc2 %d\n", L_SQC2); + if(L_BC2F>0) fprintf(fp, "bc2f %d\n", L_BC2F); + if(L_BC2FL>0) fprintf(fp, "bc2fl %d\n", L_BC2FL); + if(L_BC2T>0) fprintf(fp, "bc2t %d\n", L_BC2T); + if(L_BC2TL>0) fprintf(fp, "bc2tl %d\n", L_BC2TL); + if(L_CFC2>0) fprintf(fp, "cfc2 %d\n", L_CFC2); + if(L_CTC2>0) fprintf(fp, "ctc2 %d\n", L_CTC2); + if(L_QMFC2>0) fprintf(fp, "qmfc2 %d\n", L_QMFC2); + if(L_QMTC2>0) fprintf(fp, "qmtc2 %d\n", L_QMTC2); + if(L_VABS>0) fprintf(fp, "vabs %d\n", L_VABS); + if(L_VADD>0) fprintf(fp, "vadd %d\n", L_VADD); + if(L_VADDA>0) fprintf(fp, "vadda %d\n", L_VADDA); + if(L_VADDAi>0) fprintf(fp, "vaddai %d\n", L_VADDAi); + if(L_VADDAq>0) fprintf(fp, "vaddaq %d\n", L_VADDAq); + if(L_VADDAw>0) fprintf(fp, "vaddaw %d\n", L_VADDAw); + if(L_VADDAx>0) fprintf(fp, "vaddax %d\n", L_VADDAx); + if(L_VADDAy>0) fprintf(fp, "vadday %d\n", L_VADDAy); + if(L_VADDAz>0) fprintf(fp, "vaddaz %d\n", L_VADDAz); + if(L_VADDi>0) fprintf(fp, "vaddi %d\n", L_VADDi); + if(L_VADDq>0) fprintf(fp, "vaddq %d\n", L_VADDq); + if(L_VADDw>0) fprintf(fp, "vaddw %d\n", L_VADDw); + if(L_VADDx>0) fprintf(fp, "vaddx %d\n", L_VADDx); + if(L_VADDy>0) fprintf(fp, "vaddy %d\n", L_VADDy); + if(L_VADDz>0) fprintf(fp, "vaddz %d\n", L_VADDz); + if(L_VCALLMS>0) fprintf(fp, "vcallms %d\n", L_VCALLMS); + if(L_VCALLMSR>0) fprintf(fp, "vcallmsr %d\n", L_VCALLMSR); + if(L_VCLIPw>0) fprintf(fp, "vclip %d\n", L_VCLIPw); + if(L_VDIV>0) fprintf(fp, "vdiv %d\n", L_VDIV); + if(L_VFTOI0>0) fprintf(fp, "vftoi0 %d\n", L_VFTOI0); + if(L_VFTOI12>0) fprintf(fp, "vftoi12 %d\n", L_VFTOI12); + if(L_VFTOI15>0) fprintf(fp, "vftoi15 %d\n", L_VFTOI15); + if(L_VFTOI4>0) fprintf(fp, "vftoi14 %d\n", L_VFTOI4); + if(L_VIADD>0) fprintf(fp, "viadd %d\n", L_VIADD); + if(L_VIADDI>0) fprintf(fp, "viaddi %d\n", L_VIADDI); + if(L_VIAND>0) fprintf(fp, "viand %d\n", L_VIAND); + if(L_VILWR>0) fprintf(fp, "vilwr %d\n", L_VILWR); + if(L_VIOR>0) fprintf(fp, "vior %d\n", L_VIOR); + if(L_VISUB>0) fprintf(fp, "visub %d\n", L_VISUB); + if(L_VISWR>0) fprintf(fp, "viswr %d\n", L_VISWR); + if(L_VITOF0>0) fprintf(fp, "vitof0 %d\n", L_VITOF0); + if(L_VITOF12>0) fprintf(fp, "vitof12 %d\n", L_VITOF12); + if(L_VITOF15>0) fprintf(fp, "vitof15 %d\n", L_VITOF15); + if(L_VITOF4>0) fprintf(fp, "vitof4 %d\n", L_VITOF4); + if(L_VLQD>0) fprintf(fp, "vlqd %d\n", L_VLQD); + if(L_VLQI>0) fprintf(fp, "vlqi %d\n", L_VLQI); + if(L_VMADD>0) fprintf(fp, "vmadd %d\n", L_VMADD); + if(L_VMADDA>0) fprintf(fp, "vmadda %d\n", L_VMADDA); + if(L_VMADDAi>0) fprintf(fp, "vmaddai %d\n", L_VMADDAi); + if(L_VMADDAq>0) fprintf(fp, "vmaddaq %d\n", L_VMADDAq); + if(L_VMADDAw>0) fprintf(fp, "vmaddaw %d\n", L_VMADDAw); + if(L_VMADDAx>0) fprintf(fp, "vmaddax %d\n", L_VMADDAx); + if(L_VMADDAy>0) fprintf(fp, "vmadday %d\n", L_VMADDAy); + if(L_VMADDAz>0) fprintf(fp, "vmaddaz %d\n", L_VMADDAz); + if(L_VMADDi>0) fprintf(fp, "vmaddi %d\n", L_VMADDi); + if(L_VMADDq>0) fprintf(fp, "vmaddq %d\n", L_VMADDq); + if(L_VMADDw>0) fprintf(fp, "vmaddw %d\n", L_VMADDw); + if(L_VMADDx>0) fprintf(fp, "vmaddx %d\n", L_VMADDx); + if(L_VMADDy>0) fprintf(fp, "vmaddy %d\n", L_VMADDy); + if(L_VMADDz>0) fprintf(fp, "vmaddz %d\n", L_VMADDz); + if(L_VMAX>0) fprintf(fp, "vmax %d\n", L_VMAX); + if(L_VMAXi>0) fprintf(fp, "vmaxi %d\n", L_VMAXi); + if(L_VMAXw>0) fprintf(fp, "vmaxw %d\n", L_VMAXw); + if(L_VMAXx>0) fprintf(fp, "vmaxx %d\n", L_VMAXx); + if(L_VMAXy>0) fprintf(fp, "vmaxy %d\n", L_VMAXy); + if(L_VMAXz>0) fprintf(fp, "vmaxz %d\n", L_VMAXz); + if(L_VMFIR>0) fprintf(fp, "vmfir %d\n", L_VMFIR); + if(L_VMINI>0) fprintf(fp, "vmini %d\n", L_VMINI); + if(L_VMINIi>0) fprintf(fp, "vminii %d\n", L_VMINIi); + if(L_VMINIw>0) fprintf(fp, "vminiw %d\n", L_VMINIw); + if(L_VMINIx>0) fprintf(fp, "vminix %d\n", L_VMINIx); + if(L_VMINIy>0) fprintf(fp, "vminiy %d\n", L_VMINIy); + if(L_VMINIz>0) fprintf(fp, "vminiz %d\n", L_VMINIz); + if(L_VMOVE>0) fprintf(fp, "vmove %d\n", L_VMOVE); + if(L_VMR32>0) fprintf(fp, "vmr32 %d\n", L_VMR32); + if(L_VMSUB>0) fprintf(fp, "vmsub %d\n", L_VMSUB); + if(L_VMSUBA>0) fprintf(fp, "vmsuba %d\n", L_VMSUBA); + if(L_VMSUBAi>0) fprintf(fp, "vmsubai %d\n", L_VMSUBAi); + if(L_VMSUBAq>0) fprintf(fp, "vmsubaq %d\n", L_VMSUBAq); + if(L_VMSUBAw>0) fprintf(fp, "vmsubaw %d\n", L_VMSUBAw); + if(L_VMSUBAx>0) fprintf(fp, "vmsubax %d\n", L_VMSUBAx); + if(L_VMSUBAy>0) fprintf(fp, "vmsubay %d\n", L_VMSUBAy); + if(L_VMSUBAz>0) fprintf(fp, "vmsubaz %d\n", L_VMSUBAz); + if(L_VMSUBi>0) fprintf(fp, "vmsubi %d\n", L_VMSUBi); + if(L_VMSUBq>0) fprintf(fp, "vmsubq %d\n", L_VMSUBq); + if(L_VMSUBw>0) fprintf(fp, "vmsubw %d\n", L_VMSUBw); + if(L_VMSUBx>0) fprintf(fp, "vmsubx %d\n", L_VMSUBx); + if(L_VMSUBy>0) fprintf(fp, "vmsuby %d\n", L_VMSUBy); + if(L_VMSUBz>0) fprintf(fp, "vmsubz %d\n", L_VMSUBz); + if(L_VMTIR>0) fprintf(fp, "vmtir %d\n", L_VMTIR); + if(L_VMUL>0) fprintf(fp, "vmul %d\n", L_VMUL); + if(L_VMULA>0) fprintf(fp, "vmula %d\n", L_VMULA); + if(L_VMULAi>0) fprintf(fp, "vmulai %d\n", L_VMULAi); + if(L_VMULAq>0) fprintf(fp, "vmulaq %d\n", L_VMULAq); + if(L_VMULAw>0) fprintf(fp, "vmulaw %d\n", L_VMULAw); + if(L_VMULAx>0) fprintf(fp, "vmulax %d\n", L_VMULAx); + if(L_VMULAy>0) fprintf(fp, "vmulay %d\n", L_VMULAy); + if(L_VMULAz>0) fprintf(fp, "vmulaz %d\n", L_VMULAz); + if(L_VMULi>0) fprintf(fp, "vmuli %d\n", L_VMULi); + if(L_VMULq>0) fprintf(fp, "vmulq %d\n", L_VMULq); + if(L_VMULw>0) fprintf(fp, "vmulw %d\n", L_VMULw); + if(L_VMULx>0) fprintf(fp, "vmulx %d\n", L_VMULx); + if(L_VMULy>0) fprintf(fp, "vmuly %d\n", L_VMULy); + if(L_VMULz>0) fprintf(fp, "vmulz %d\n", L_VMULz); + if(L_VNOP>0) fprintf(fp, "vnop %d\n", L_VNOP); + if(L_VOPMSUB>0) fprintf(fp, "vopmsub %d\n", L_VOPMSUB); + if(L_VOPMULA>0) fprintf(fp, "vopmula %d\n", L_VOPMULA); + if(L_VRGET>0) fprintf(fp, "vrget %d\n", L_VRGET); + if(L_VRINIT>0) fprintf(fp, "vrinit %d\n", L_VRINIT); + if(L_VRNEXT>0) fprintf(fp, "vrnext %d\n", L_VRNEXT); + if(L_VRSQRT>0) fprintf(fp, "vrsqrt %d\n", L_VRSQRT); + if(L_VRXOR>0) fprintf(fp, "vrxor %d\n", L_VRXOR); + if(L_VSQD>0) fprintf(fp, "vsqd %d\n", L_VSQD); + if(L_VSQI>0) fprintf(fp, "vsqi %d\n", L_VSQI); + if(L_VSQRT>0) fprintf(fp, "vsqrt %d\n", L_VSQRT ); + if(L_VSUB>0) fprintf(fp, "vsub %d\n", L_VSUB); + if(L_VSUBA>0) fprintf(fp, "vsuba %d\n", L_VSUBA); + if(L_VSUBAi>0) fprintf(fp, "vsubai %d\n", L_VSUBAi); + if(L_VSUBAq>0) fprintf(fp, "vsubaq %d\n", L_VSUBAq); + if(L_VSUBAw>0) fprintf(fp, "vsubaw %d\n", L_VSUBAw); + if(L_VSUBAx>0) fprintf(fp, "vsubax %d\n", L_VSUBAx); + if(L_VSUBAy>0) fprintf(fp, "vsubay %d\n", L_VSUBAy); + if(L_VSUBAz>0) fprintf(fp, "vsubaz %d\n", L_VSUBAz); + if(L_VSUBi>0) fprintf(fp, "vsubi %d\n", L_VSUBi); + if(L_VSUBq>0) fprintf(fp, "vsubq %d\n", L_VSUBq); + if(L_VSUBw>0) fprintf(fp, "vsubw %d\n", L_VSUBw); + if(L_VSUBx>0) fprintf(fp, "vsubx %d\n", L_VSUBx); + if(L_VSUBy>0) fprintf(fp, "vsuby %d\n", L_VSUBy); + if(L_VSUBz>0) fprintf(fp, "vsubz %d\n", L_VSUBz); + if(L_VWAITQ>0) fprintf(fp, "vwaitq %d\n", L_VWAITQ); + + fclose(fp); + +} + + + + + + + + + + + +/***************/ +//R5900 +void LT_SPECIAL() {LT_SpecialPrintTable[_Funct_]();} +void LT_REGIMM() {LT_REGIMMPrintTable[_Rt_](); } +void LT_UnknownOpcode() {} +void LT_ADDI() { L_ADDI++;} +void LT_ADDIU() { L_ADDIU++;} +void LT_DADDI() { L_DADDI++;} +void LT_DADDIU(){ L_DADDIU++;} +void LT_ANDI() { L_ANDI++;} +void LT_ORI() { L_ORI++;} +void LT_XORI() {L_XORI++;} +void LT_SLTI() {L_SLTI++;} +void LT_SLTIU() {L_SLTIU++;} +void LT_ADD() { L_ADD++;} +void LT_ADDU() { L_ADDU++;} +void LT_DADD() { L_DADD++;} +void LT_DADDU() { L_DADDU++;} +void LT_SUB() { L_SUB++;} +void LT_SUBU() { L_SUBU++;} +void LT_DSUB() { L_DSUB++;} +void LT_DSUBU() { L_DSUBU++;} +void LT_AND() { L_AND++;} +void LT_OR() { L_OR++;} +void LT_XOR() { L_XOR++;} +void LT_NOR() { L_NOR++;} +void LT_SLT() { L_SLT++;} +void LT_SLTU() { L_SLTU++;} +void LT_J() { L_J++;} +void LT_JAL() { L_JAL++;} +void LT_JR() { L_JR++;} +void LT_JALR() { L_JALR++;} +void LT_DIV() { L_DIV++;} +void LT_DIVU() { L_DIVU++;} +void LT_MULT() { L_MULT++;} +void LT_MULTU() { L_MULTU++;} +void LT_LUI() { L_LUI++;} +void LT_MFHI() { L_MFHI++;} +void LT_MFLO() { L_MFLO++;} +void LT_MTHI() { L_MTHI++;} +void LT_MTLO() { L_MTLO++;} +void LT_SLL() { L_SLL++;} +void LT_DSLL() { L_DSLL++;} +void LT_DSLL32(){ L_DSLL32++;} +void LT_SRA() { L_SRA++;} +void LT_DSRA() { L_DSRA++;} +void LT_DSRA32(){ L_DSRA32++;} +void LT_SRL() { L_SRL++;} +void LT_DSRL() { L_DSRL++;} +void LT_DSRL32(){ L_DSRL32++;} +void LT_SLLV() { L_SLLV++;} +void LT_SRAV() { L_SRAV++;} +void LT_SRLV() { L_SRLV++;} +void LT_DSLLV() { L_DSLLV++;} +void LT_DSRAV() { L_DSRAV++;} +void LT_DSRLV() { L_DSRLV++;} +void LT_BEQ() { L_BEQ++;} +void LT_BNE() { L_BNE++;} +void LT_BGEZ() { L_BGEZ++;} +void LT_BGEZAL(){ L_BGEZAL++;} +void LT_BGTZ() { L_BGTZ++;} +void LT_BLEZ() { L_BLEZ++;} +void LT_BLTZ() { L_BLTZ++;} +void LT_BLTZAL(){ L_BLTZAL++;} +void LT_BEQL() { L_BEQL++;} +void LT_BNEL() { L_BNEL++;} +void LT_BLEZL() { L_BLEZL++;} +void LT_BGTZL() { L_BGTZL++;} +void LT_BLTZL() { L_BLTZL++;} +void LT_BGEZL() { L_BGEZL++;} +void LT_BLTZALL(){ L_BLTZALL++;} +void LT_BGEZALL(){ L_BGEZALL++;} +void LT_LB() {L_LB++;} +void LT_LBU() {L_LBU++;} +void LT_LH() {L_LH++;} +void LT_LHU() {L_LHU++;} +void LT_LW() {L_LW++;} +void LT_LWU() {L_LWU++;} +void LT_LWL() {L_LWL++;} +void LT_LWR() {L_LWR++;} +void LT_LD() {L_LD++;} +void LT_LDL() {L_LDL++;} +void LT_LDR() {L_LDR++;} +void LT_LQ() {L_LQ++;} +void LT_SB() {L_SB++;} +void LT_SH() {L_SH++;} +void LT_SW() {L_SW++;} +void LT_SWL() {L_SWL++;} +void LT_SWR() {L_SWR++;} +void LT_SD() {L_SD++;} +void LT_SDL() {L_SDL++;} +void LT_SDR() {L_SDR++;} +void LT_SQ() {L_SQ++;} +void LT_MOVZ() {L_MOVZ++;} +void LT_MOVN() {L_MOVN++;} +void LT_SYSCALL() {L_SYSCALL++;} +void LT_BREAK() {L_BREAK++;} +void LT_CACHE() {L_CACHE++;} +void LT_MFSA() {L_MFSA++;} +void LT_MTSA() {L_MTSA++;} +void LT_SYNC() {L_SYNC++;} +void LT_PREF() {L_PREF++;} +void LT_TGE() {L_TGE++;} +void LT_TGEU() {L_TGEU++;} +void LT_TLT() {L_TLT++;} +void LT_TLTU() {L_TLTU++;} +void LT_TEQ() {L_TEQ++;} +void LT_TNE() {L_TNE++;} +void LT_TGEI() {L_TGEI++;} +void LT_TGEIU() {L_TGEIU++;} +void LT_TLTI() {L_TLTI++;} +void LT_TLTIU() {L_TLTIU++;} +void LT_TEQI() {L_TEQI++;} +void LT_TNEI() {L_TNEI++;} +void LT_MTSAB() {L_MTSAB++;} +void LT_MTSAH() {L_MTSAH++;} +//cop0 +void LT_COP0(){ LT_COP0PrintTable[_Rs_]();} +void LT_COP0_BC0() {LT_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03]();} +void LT_COP0_Func() { LT_COP0C0PrintTable[_Funct_](); } +void LT_COP0_Unknown() { } +void LT_MFC0() {L_MFC0++;} +void LT_MTC0() {L_MTC0++;} +void LT_BC0F() {L_BC0F++;} +void LT_BC0T() {L_BC0T++;} +void LT_BC0FL(){L_BC0FL++;} +void LT_BC0TL(){L_BC0TL++;} +void LT_TLBR() {L_TLBR++;} +void LT_TLBWI(){L_TLBWI++;} +void LT_TLBWR(){L_TLBWR++;} +void LT_TLBP() {L_TLBP++;} +void LT_ERET() {L_ERET++;} +void LT_DI() {L_DI++;} +void LT_EI() {L_EI++;} +//mmi +void LT_MMI() {LT_MMIPrintTable[_Funct_]();} +void LT_MMI0() {LT_MMI0PrintTable[_Sa_]();} +void LT_MMI1() {LT_MMI1PrintTable[_Sa_]();} +void LT_MMI2() {LT_MMI2PrintTable[_Sa_]();} +void LT_MMI3() {LT_MMI3PrintTable[_Sa_]();} +void LT_MMI_Unknown() {} +void LT_MADD() {L_MADD++;} +void LT_MADDU(){L_MADDU++;} +void LT_PLZCW(){L_PLZCW++;} +void LT_MADD1(){L_MADD1++;} +void LT_MADDU1(){L_MADDU1++;} +void LT_MFHI1(){L_MFHI1++;} +void LT_MTHI1(){L_MTHI1++;} +void LT_MFLO1(){L_MFLO1++;} +void LT_MTLO1(){L_MTLO1++;} +void LT_MULT1(){L_MULT1++;} +void LT_MULTU1(){L_MULTU1++;} +void LT_DIV1(){L_DIV1++;} +void LT_DIVU1(){L_DIVU1++;} +void LT_PMFHL(){L_PMFHL++;} +void LT_PMTHL(){L_PMTHL++;} +void LT_PSLLH(){L_PSLLH++;} +void LT_PSRLH(){L_PSRLH++;} +void LT_PSRAH(){L_PSRAH++;} +void LT_PSLLW(){L_PSLLW++;} +void LT_PSRLW(){L_PSRLW++;} +void LT_PSRAW(){L_PSRAW++;} +void LT_PADDW(){L_PADDW++;} +void LT_PSUBW(){L_PSUBW++;} +void LT_PCGTW(){L_PCGTW++;} +void LT_PMAXW(){L_PMAXW++;} +void LT_PADDH(){L_PADDH++;} +void LT_PSUBH(){L_PSUBH++;} +void LT_PCGTH(){L_PCGTH++;} +void LT_PMAXH(){L_PMAXH++;} +void LT_PADDB(){L_PADDB++;} +void LT_PSUBB(){L_PSUBB++;} +void LT_PCGTB(){L_PCGTB++;} +void LT_PADDSW(){L_PADDSW++;} +void LT_PSUBSW(){L_PSUBSW++;} +void LT_PEXTLW(){L_PEXTLW++;} +void LT_PPACW(){L_PPACW++;} +void LT_PADDSH(){L_PADDSH++;} +void LT_PSUBSH(){L_PSUBSH++;} +void LT_PEXTLH(){L_PEXTLH++;} +void LT_PPACH(){L_PPACH++;} +void LT_PADDSB(){L_PADDSB++;} +void LT_PSUBSB(){L_PSUBSB++;} +void LT_PEXTLB(){L_PEXTLB++;} +void LT_PPACB(){L_PPACB++;} +void LT_PEXT5(){L_PEXT5++;} +void LT_PPAC5(){L_PPAC5++;} +void LT_PABSW(){L_PABSW++;} +void LT_PCEQW(){L_PCEQW++;} +void LT_PMINW(){L_PMINW++;} +void LT_PADSBH(){L_PADSBH++;} +void LT_PABSH(){L_PABSH++;} +void LT_PCEQH(){L_PCEQH++;} +void LT_PMINH(){L_PMINH++;} +void LT_PCEQB(){L_PCEQB++;} +void LT_PADDUW(){L_PADDUW++;} +void LT_PSUBUW(){L_PSUBUW++;} +void LT_PEXTUW(){L_PEXTUW++;} +void LT_PADDUH(){L_PADDUH++;} +void LT_PSUBUH(){L_PSUBUH++;} +void LT_PEXTUH(){L_PEXTUH++;} +void LT_PADDUB(){L_PADDUB++;} +void LT_PSUBUB(){L_PSUBUB++;} +void LT_PEXTUB(){L_PEXTUB++;} +void LT_QFSRV(){L_QFSRV++;} +void LT_PMADDW(){L_PMADDW++;} +void LT_PSLLVW(){L_PSLLVW++;} +void LT_PSRLVW(){L_PSRLVW++;} +void LT_PMSUBW(){L_PMSUBW++;} +void LT_PMFHI(){L_PMFHI++;} +void LT_PMFLO(){L_PMFLO++;} +void LT_PINTH(){L_PINTH++;} +void LT_PMULTW(){L_PMULTW++;} +void LT_PDIVW(){L_PDIVW++;} +void LT_PCPYLD(){L_PCPYLD++;} +void LT_PMADDH(){L_PMADDH++;} +void LT_PHMADH(){L_PHMADH++;} +void LT_PAND(){L_PAND++;} +void LT_PXOR(){L_PXOR++;} +void LT_PMSUBH(){L_PMSUBH++;} +void LT_PHMSBH(){L_PHMSBH++;} +void LT_PEXEH(){L_PEXEH++;} +void LT_PREVH(){L_PREVH++;} +void LT_PMULTH(){L_PMULTH++;} +void LT_PDIVBW(){L_PDIVBW++;} +void LT_PEXEW(){L_PEXEW++;} +void LT_PROT3W(){L_PROT3W++;} +void LT_PMADDUW(){L_PMADDUW++;} +void LT_PSRAVW(){L_PSRAVW++;} +void LT_PMTHI(){L_MTHI++;} +void LT_PMTLO(){L_PMTLO++;} +void LT_PINTEH(){L_PINTEH++;} +void LT_PMULTUW(){L_PMULTUW++;} +void LT_PDIVUW(){L_PDIVUW++;} +void LT_PCPYUD(){L_PCPYUD++;} +void LT_POR(){L_POR++;} +void LT_PNOR(){L_PNOR++;} +void LT_PEXCH(){L_PEXCH++;} +void LT_PCPYH(){L_PCPYH++;} +void LT_PEXCW(){L_PEXCW++;} +//COP1 +void LT_COP1() {LT_COP1PrintTable[_Rs_]();} +void LT_LWC1() {L_LWC1++;} +void LT_SWC1() {L_SWC1++;} +void LT_COP1_BC1() {LT_COP1BC1PrintTable[_Rt_]();} +void LT_COP1_S() {LT_COP1SPrintTable[_Funct_]();} +void LT_COP1_W() {LT_COP1WPrintTable[_Funct_]();} +void LT_COP1_Unknown() {} +void LT_MFC1(){L_MFC1++;} +void LT_CFC1(){L_CFC1++;} +void LT_MTC1(){L_MTC1++;} +void LT_CTC1(){L_CTC1++;} +void LT_BC1F(){L_BC1F++;} +void LT_BC1T(){L_BC1T++;} +void LT_BC1FL(){L_BC1FL++;} +void LT_BC1TL(){L_BC1TL++;} +void LT_ADD_S(){L_ADD_S++;} +void LT_SUB_S(){L_SUB_S++;} +void LT_MUL_S(){L_MUL_S++;} +void LT_DIV_S(){L_DIV_S++;} +void LT_SQRT_S(){L_SQRT_S++;} +void LT_ABS_S(){L_ABS_S++;} +void LT_MOV_S(){L_MOV_S++;} +void LT_NEG_S(){L_NEG_S++;} +void LT_RSQRT_S(){L_RSQRT_S++;} +void LT_ADDA_S(){L_ADDA_S++;} +void LT_SUBA_S(){L_SUBA_S++;} +void LT_MULA_S(){L_MULA_S++;} +void LT_MADD_S(){L_MADD_S++;} +void LT_MSUB_S(){L_MSUB_S++;} +void LT_MADDA_S(){L_MADDA_S++;} +void LT_MSUBA_S(){L_MSUBA_S++;} +void LT_CVT_W(){L_CVT_W++;} +void LT_MAX_S(){L_MAX_S++;} +void LT_MIN_S(){L_MIN_S++;} +void LT_C_F(){L_C_F++;} +void LT_C_EQ(){L_C_EQ++;} +void LT_C_LT(){L_C_LT++;} +void LT_C_LE(){L_C_LE++;} +void LT_CVT_S(){L_CVT_S++;} +//cop2 + +void LT_LQC2() {L_LQC2++;} +void LT_SQC2() {L_SQC2++;} +void LT_COP2() {LT_COP2PrintTable[_Rs_]();} +void LT_COP2_BC2() {LT_COP2BC2PrintTable[_Rt_]();} +void LT_COP2_SPECIAL() { LT_COP2SPECIAL1PrintTable[_Funct_]();} +void LT_COP2_SPECIAL2() {LT_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)]();} +void LT_COP2_Unknown(){} +void LT_QMFC2(){L_QMFC2++;} +void LT_CFC2(){L_CFC2++;} +void LT_QMTC2(){L_QMTC2++;} +void LT_CTC2(){L_CTC2++;} +void LT_BC2F(){L_BC2F++;} +void LT_BC2T(){L_BC2T++;} +void LT_BC2FL(){L_BC2FL++;} +void LT_BC2TL(){L_BC2TL++;} +void LT_VADDx(){L_VADDx++;} +void LT_VADDy(){L_VADDy++;} +void LT_VADDz(){L_VADDz++;} +void LT_VADDw(){L_VADDw++;} +void LT_VSUBx(){L_VSUBx++;} +void LT_VSUBy(){L_VSUBy++;} +void LT_VSUBz(){L_VSUBz++;} +void LT_VSUBw(){L_VSUBw++;} +void LT_VMADDx(){L_VMADDx++;} +void LT_VMADDy(){L_VMADDy++;} +void LT_VMADDz(){L_VMADDz++;} +void LT_VMADDw(){L_VMADDw++;} +void LT_VMSUBx(){L_VMSUBx++;} +void LT_VMSUBy(){L_VMSUBy++;} +void LT_VMSUBz(){L_VMSUBz++;} +void LT_VMSUBw(){L_VMSUBw++;} +void LT_VMAXx(){L_VMAXx++;} +void LT_VMAXy(){L_VMAXy++;} +void LT_VMAXz(){L_VMAXz++;} +void LT_VMAXw(){L_VMAXw++;} +void LT_VMINIx(){L_VMINIx++;} +void LT_VMINIy(){L_VMINIy++;} +void LT_VMINIz(){L_VMINIz++;} +void LT_VMINIw(){L_VMINIw++;} +void LT_VMULx(){L_VMULx++;} +void LT_VMULy(){L_VMULy++;} +void LT_VMULz(){L_VMULz++;} +void LT_VMULw(){L_VMULw++;} +void LT_VMULq(){L_VMULq++;} +void LT_VMAXi(){L_VMAXi++;} +void LT_VMULi(){L_VMULi++;} +void LT_VMINIi(){L_VMINIi++;} +void LT_VADDq(){L_VADDq++;} +void LT_VMADDq(){L_VMADDq++;} +void LT_VADDi(){L_VADDi++;} +void LT_VMADDi(){L_VMADDi++;} +void LT_VSUBq(){L_VSUBq++;} +void LT_VMSUBq(){L_VMSUBq++;} +void LT_VSUBi(){L_VSUBi++;} +void LT_VMSUBi(){L_VMSUBi++;} +void LT_VADD(){L_VADD++;} +void LT_VMADD(){L_VMADD++;} +void LT_VMUL(){L_VMUL++;} +void LT_VMAX(){L_VMAX++;} +void LT_VSUB(){L_VSUB++;} +void LT_VMSUB(){L_VMSUB++;} +void LT_VOPMSUB(){L_VOPMSUB++;} +void LT_VMINI(){L_VMINI++;} +void LT_VIADD(){L_VIADD++;} +void LT_VISUB(){L_VISUB++;} +void LT_VIADDI(){L_VIADDI++;} +void LT_VIAND(){L_VIAND++;} +void LT_VIOR(){L_VIOR++;} +void LT_VCALLMS(){L_VCALLMS++;} +void LT_VCALLMSR(){L_VCALLMSR++;} +void LT_VADDAx(){L_VADDAx++;} +void LT_VADDAy(){L_VADDAy++;} +void LT_VADDAz(){L_VADDAz++;} +void LT_VADDAw(){L_VADDAw++;} +void LT_VSUBAx(){L_VSUBAx++;} +void LT_VSUBAy(){L_VSUBAy++;} +void LT_VSUBAz(){L_VSUBAz++;} +void LT_VSUBAw(){L_VSUBAw++;} +void LT_VMADDAx(){L_VMADDAx++;} +void LT_VMADDAy(){L_VMADDAy++;} +void LT_VMADDAz(){L_VMADDAz++;} +void LT_VMADDAw(){L_VMADDAw++;} +void LT_VMSUBAx(){L_VMSUBAx++;} +void LT_VMSUBAy(){L_VMSUBAy++;} +void LT_VMSUBAz(){L_VMSUBAz++;} +void LT_VMSUBAw(){L_VMSUBAw++;} +void LT_VITOF0(){L_VITOF0++;} +void LT_VITOF4(){L_VITOF4++;} +void LT_VITOF12(){L_VITOF12++;} +void LT_VITOF15(){L_VITOF15++;} +void LT_VFTOI0(){L_VFTOI0++;} +void LT_VFTOI4(){L_VFTOI4++;} +void LT_VFTOI12(){L_VFTOI12++;} +void LT_VFTOI15(){L_VFTOI15++;} +void LT_VMULAx(){L_VMULAx++;} +void LT_VMULAy(){L_VMULAy++;} +void LT_VMULAz(){L_VMULAz++;} +void LT_VMULAw(){L_VMULAw++;} +void LT_VMULAq(){L_VMULAq++;} +void LT_VABS(){L_VABS++;} +void LT_VMULAi(){L_VMULAi++;} +void LT_VCLIPw(){L_VCLIPw++;} +void LT_VADDAq(){L_VADDAq++;} +void LT_VMADDAq(){L_VMADDAq++;} +void LT_VADDAi(){L_VADDAi++;} +void LT_VMADDAi(){L_VMADDAi++;} +void LT_VSUBAq(){L_VSUBAq++;} +void LT_VMSUBAq(){L_VMSUBAq++;} +void LT_VSUBAi(){L_VSUBAi++;} +void LT_VMSUBAi(){L_VMSUBAi++;} +void LT_VADDA(){L_VADDA++;} +void LT_VMADDA(){L_VMADDA++;} +void LT_VMULA(){L_VMULA++;} +void LT_VSUBA(){L_VSUBA++;} +void LT_VMSUBA(){L_VMSUBA++;} +void LT_VOPMULA(){L_VOPMULA++;} +void LT_VNOP(){L_VNOP++;} +void LT_VMOVE(){L_VMOVE++;} +void LT_VMR32(){L_VMR32++;} +void LT_VLQI(){L_VLQI++;} +void LT_VSQI(){L_VSQI++;} +void LT_VLQD(){L_VLQD++;} +void LT_VSQD(){L_VSQD++;} +void LT_VDIV(){L_VDIV++;} +void LT_VSQRT(){L_VSQRT++;} +void LT_VRSQRT(){L_VRSQRT++;} +void LT_VWAITQ(){L_VWAITQ++;} +void LT_VMTIR(){L_VMTIR++;} +void LT_VMFIR(){L_VMFIR++;} +void LT_VILWR(){L_VILWR++;} +void LT_VISWR(){L_VISWR++;} +void LT_VRNEXT(){L_VRNEXT++;} +void LT_VRGET(){L_VRGET++;} +void LT_VRINIT(){L_VRINIT++;} +void LT_VRXOR(){L_VRXOR++;} + +void (*LT_OpcodePrintTable[64])() = +{ + LT_SPECIAL, LT_REGIMM, LT_J, LT_JAL, LT_BEQ, LT_BNE, LT_BLEZ, LT_BGTZ, + LT_ADDI, LT_ADDIU, LT_SLTI, LT_SLTIU, LT_ANDI, LT_ORI, LT_XORI, LT_LUI, + LT_COP0, LT_COP1, LT_COP2, LT_UnknownOpcode, LT_BEQL, LT_BNEL, LT_BLEZL, LT_BGTZL, + LT_DADDI, LT_DADDIU, LT_LDL, LT_LDR, LT_MMI, LT_UnknownOpcode, LT_LQ, LT_SQ, + LT_LB, LT_LH, LT_LWL, LT_LW, LT_LBU, LT_LHU, LT_LWR, LT_LWU, + LT_SB, LT_SH, LT_SWL, LT_SW, LT_SDL, LT_SDR, LT_SWR, LT_CACHE, + LT_UnknownOpcode, LT_LWC1, LT_UnknownOpcode, LT_PREF, LT_UnknownOpcode,LT_UnknownOpcode, LT_LQC2, LT_LD, + LT_UnknownOpcode, LT_SWC1, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode,LT_UnknownOpcode, LT_SQC2, LT_SD +}; + + +void (*LT_SpecialPrintTable[64])() = +{ + LT_SLL, LT_UnknownOpcode, LT_SRL, LT_SRA, LT_SLLV, LT_UnknownOpcode, LT_SRLV, LT_SRAV, + LT_JR, LT_JALR, LT_MOVZ, LT_MOVN, LT_SYSCALL, LT_BREAK, LT_UnknownOpcode, LT_SYNC, + LT_MFHI, LT_MTHI, LT_MFLO, LT_MTLO, LT_DSLLV, LT_UnknownOpcode, LT_DSRLV, LT_DSRAV, + LT_MULT, LT_MULTU, LT_DIV, LT_DIVU, LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode, + LT_ADD, LT_ADDU, LT_SUB, LT_SUBU, LT_AND, LT_OR, LT_XOR, LT_NOR, + LT_MFSA , LT_MTSA , LT_SLT, LT_SLTU, LT_DADD, LT_DADDU, LT_DSUB, LT_DSUBU, + LT_TGE, LT_TGEU, LT_TLT, LT_TLTU, LT_TEQ, LT_UnknownOpcode, LT_TNE, LT_UnknownOpcode, + LT_DSLL, LT_UnknownOpcode, LT_DSRL, LT_DSRA, LT_DSLL32, LT_UnknownOpcode, LT_DSRL32, LT_DSRA32 +}; + +void (*LT_REGIMMPrintTable[32])() = { + LT_BLTZ, LT_BGEZ, LT_BLTZL, LT_BGEZL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_TGEI, LT_TGEIU, LT_TLTI, LT_TLTIU, LT_TEQI, LT_UnknownOpcode, LT_TNEI, LT_UnknownOpcode, + LT_BLTZAL, LT_BGEZAL, LT_BLTZALL, LT_BGEZALL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_MTSAB, LT_MTSAH , LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, +}; +void (*LT_MMIPrintTable[64])() = +{ + LT_MADD, LT_MADDU, LT_MMI_Unknown, LT_MMI_Unknown, LT_PLZCW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI0, LT_MMI2, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MFHI1, LT_MTHI1, LT_MFLO1, LT_MTLO1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MULT1, LT_MULTU1, LT_DIV1, LT_DIVU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MADD1, LT_MADDU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI1 , LT_MMI3, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHL, LT_PMTHL, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLH, LT_MMI_Unknown, LT_PSRLH, LT_PSRAH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLW, LT_MMI_Unknown, LT_PSRLW, LT_PSRAW, +}; + +void (*LT_MMI0PrintTable[32])() = +{ + LT_PADDW, LT_PSUBW, LT_PCGTW, LT_PMAXW, + LT_PADDH, LT_PSUBH, LT_PCGTH, LT_PMAXH, + LT_PADDB, LT_PSUBB, LT_PCGTB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDSW, LT_PSUBSW, LT_PEXTLW, LT_PPACW, + LT_PADDSH, LT_PSUBSH, LT_PEXTLH, LT_PPACH, + LT_PADDSB, LT_PSUBSB, LT_PEXTLB, LT_PPACB, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXT5, LT_PPAC5, +}; + +void (*LT_MMI1PrintTable[32])() = +{ + LT_MMI_Unknown, LT_PABSW, LT_PCEQW, LT_PMINW, + LT_PADSBH, LT_PABSH, LT_PCEQH, LT_PMINH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PCEQB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDUW, LT_PSUBUW, LT_PEXTUW, LT_MMI_Unknown, + LT_PADDUH, LT_PSUBUH, LT_PEXTUH, LT_MMI_Unknown, + LT_PADDUB, LT_PSUBUB, LT_PEXTUB, LT_QFSRV, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, +}; + + +void (*LT_MMI2PrintTable[32])() = +{ + LT_PMADDW, LT_MMI_Unknown, LT_PSLLVW, LT_PSRLVW, + LT_PMSUBW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHI, LT_PMFLO, LT_PINTH, LT_MMI_Unknown, + LT_PMULTW, LT_PDIVW, LT_PCPYLD, LT_MMI_Unknown, + LT_PMADDH, LT_PHMADH, LT_PAND, LT_PXOR, + LT_PMSUBH, LT_PHMSBH, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXEH, LT_PREVH, + LT_PMULTH, LT_PDIVBW, LT_PEXEW, LT_PROT3W, +}; + +void (*LT_MMI3PrintTable[32])() = +{ + LT_PMADDUW, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSRAVW, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMTHI, LT_PMTLO, LT_PINTEH, LT_MMI_Unknown, + LT_PMULTUW, LT_PDIVUW, LT_PCPYUD, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_POR, LT_PNOR, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCH, LT_PCPYH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCW, LT_MMI_Unknown, +}; + +void (*LT_COP0PrintTable[32])() = +{ + LT_MFC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_MTC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_BC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Func, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0BC0PrintTable[32])() = +{ + LT_BC0F, LT_BC0T, LT_BC0FL, LT_BC0TL, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0C0PrintTable[64])() = { + LT_COP0_Unknown, LT_TLBR, LT_TLBWI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_TLBWR, LT_COP0_Unknown, + LT_TLBP, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_ERET, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_EI, LT_DI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown +}; + + +void (*LT_COP1PrintTable[32])() = { + LT_MFC1, LT_COP1_Unknown, LT_CFC1, LT_COP1_Unknown, LT_MTC1, LT_COP1_Unknown, LT_CTC1, LT_COP1_Unknown, + LT_COP1_BC1, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_S, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_W, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1BC1PrintTable[32])() = { + LT_BC1F, LT_BC1T, LT_BC1FL, LT_BC1TL, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1SPrintTable[64])() = { +LT_ADD_S, LT_SUB_S, LT_MUL_S, LT_DIV_S, LT_SQRT_S, LT_ABS_S, LT_MOV_S, LT_NEG_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_RSQRT_S, LT_COP1_Unknown, +LT_ADDA_S, LT_SUBA_S, LT_MULA_S, LT_COP1_Unknown,LT_MADD_S, LT_MSUB_S, LT_MADDA_S, LT_MSUBA_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_CVT_W, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_MAX_S, LT_MIN_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_C_F, LT_COP1_Unknown,LT_C_EQ, LT_COP1_Unknown,LT_C_LT, LT_COP1_Unknown,LT_C_LE, LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP1WPrintTable[64])() = { +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_CVT_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP2PrintTable[32])() = { + LT_COP2_Unknown, LT_QMFC2, LT_CFC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_QMTC2, LT_CTC2, LT_COP2_Unknown, + LT_COP2_BC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, +}; + +void (*LT_COP2BC2PrintTable[32])() = { + LT_BC2F, LT_BC2T, LT_BC2FL, LT_BC2TL, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, +}; + +void (*LT_COP2SPECIAL1PrintTable[64])() = +{ + LT_VADDx, LT_VADDy, LT_VADDz, LT_VADDw, LT_VSUBx, LT_VSUBy, LT_VSUBz, LT_VSUBw, + LT_VMADDx, LT_VMADDy, LT_VMADDz, LT_VMADDw, LT_VMSUBx, LT_VMSUBy, LT_VMSUBz, LT_VMSUBw, + LT_VMAXx, LT_VMAXy, LT_VMAXz, LT_VMAXw, LT_VMINIx, LT_VMINIy, LT_VMINIz, LT_VMINIw, + LT_VMULx, LT_VMULy, LT_VMULz, LT_VMULw, LT_VMULq, LT_VMAXi, LT_VMULi, LT_VMINIi, + LT_VADDq, LT_VMADDq, LT_VADDi, LT_VMADDi, LT_VSUBq, LT_VMSUBq, LT_VSUBi, LT_VMSUBi, + LT_VADD, LT_VMADD, LT_VMUL, LT_VMAX, LT_VSUB, LT_VMSUB, LT_VOPMSUB, LT_VMINI, + LT_VIADD, LT_VISUB, LT_VIADDI, LT_COP2_Unknown,LT_VIAND, LT_VIOR, LT_COP2_Unknown, LT_COP2_Unknown, + LT_VCALLMS, LT_VCALLMSR, LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2, +}; + +void (*LT_COP2SPECIAL2PrintTable[128])() = +{ + LT_VADDAx ,LT_VADDAy ,LT_VADDAz ,LT_VADDAw ,LT_VSUBAx ,LT_VSUBAy ,LT_VSUBAz ,LT_VSUBAw, + LT_VMADDAx ,LT_VMADDAy ,LT_VMADDAz ,LT_VMADDAw ,LT_VMSUBAx ,LT_VMSUBAy ,LT_VMSUBAz ,LT_VMSUBAw, + LT_VITOF0 ,LT_VITOF4 ,LT_VITOF12 ,LT_VITOF15 ,LT_VFTOI0 ,LT_VFTOI4 ,LT_VFTOI12 ,LT_VFTOI15, + LT_VMULAx ,LT_VMULAy ,LT_VMULAz ,LT_VMULAw ,LT_VMULAq ,LT_VABS ,LT_VMULAi ,LT_VCLIPw, + LT_VADDAq ,LT_VMADDAq ,LT_VADDAi ,LT_VMADDAi ,LT_VSUBAq ,LT_VMSUBAq ,LT_VSUBAi ,LT_VMSUBAi, + LT_VADDA ,LT_VMADDA ,LT_VMULA ,LT_COP2_Unknown,LT_VSUBA ,LT_VMSUBA ,LT_VOPMULA ,LT_VNOP, + LT_VMOVE ,LT_VMR32 ,LT_COP2_Unknown,LT_COP2_Unknown,LT_VLQI ,LT_VSQI ,LT_VLQD ,LT_VSQD, + LT_VDIV ,LT_VSQRT ,LT_VRSQRT ,LT_VWAITQ ,LT_VMTIR ,LT_VMFIR ,LT_VILWR ,LT_VISWR, + LT_VRNEXT ,LT_VRGET ,LT_VRINIT ,LT_VRXOR ,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, +}; diff --git a/DebugTools/cpuopsDebug.h b/DebugTools/cpuopsDebug.h new file mode 100644 index 0000000000..3422693198 --- /dev/null +++ b/DebugTools/cpuopsDebug.h @@ -0,0 +1,456 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void UpdateR5900op(); +extern void (*LT_OpcodePrintTable[64])(); +extern void (*LT_SpecialPrintTable[64])(); +extern void (*LT_REGIMMPrintTable[32])(); +extern void (*LT_MMIPrintTable[64])(); +extern void (*LT_MMI0PrintTable[32])(); +extern void (*LT_MMI1PrintTable[32])(); +extern void (*LT_MMI2PrintTable[32])(); +extern void (*LT_MMI3PrintTable[32])(); +extern void (*LT_COP0PrintTable[32])(); +extern void (*LT_COP0BC0PrintTable[32])(); +extern void (*LT_COP0C0PrintTable[64])(); +extern void (*LT_COP1PrintTable[32])(); +extern void (*LT_COP1BC1PrintTable[32])(); +extern void (*LT_COP1SPrintTable[64])(); +extern void (*LT_COP1WPrintTable[64])(); +extern void (*LT_COP2PrintTable[32])(); +extern void (*LT_COP2BC2PrintTable[32])(); +extern void (*LT_COP2SPECIAL1PrintTable[64])(); +extern void (*LT_COP2SPECIAL2PrintTable[128])(); +// **********************Standard Opcodes************************** +int L_ADD=0; +int L_ADDI=0; +int L_ADDIU=0; +int L_ADDU=0; +int L_AND=0; +int L_ANDI=0; +int L_BEQ=0; +int L_BEQL=0; +int L_BGEZ=0; +int L_BGEZAL=0; +int L_BGEZALL=0; +int L_BGEZL=0; +int L_BGTZ=0; +int L_BGTZL=0; +int L_BLEZ=0; +int L_BLEZL=0; +int L_BLTZ=0; +int L_BLTZAL=0; +int L_BLTZALL=0; +int L_BLTZL=0; +int L_BNE=0; +int L_BNEL=0; +int L_BREAK=0; +int L_CACHE=0; +int L_DADD=0; +int L_DADDI=0; +int L_DADDIU=0; +int L_DADDU=0; +int L_DIV=0; +int L_DIVU=0; +int L_DSLL=0; +int L_DSLL32=0; +int L_DSLLV=0; +int L_DSRA=0; +int L_DSRA32=0; +int L_DSRAV=0; +int L_DSRL=0; +int L_DSRL32=0; +int L_DSRLV=0; +int L_DSUB=0; +int L_DSUBU=0; +int L_J=0; +int L_JAL=0; +int L_JALR=0; +int L_JR=0; +int L_LB=0; +int L_LBU=0; +int L_LD=0; +int L_LDL=0; +int L_LDR=0; +int L_LH=0; +int L_LHU=0; +int L_LQ=0; +int L_LQC2=0; +int L_LUI=0; +int L_LW=0; +int L_LWC1=0; +int L_LWL=0; +int L_LWR=0; +int L_LWU=0; +int L_MFHI=0; +int L_MFLO=0; +int L_MFSA=0; +int L_MOVN=0; +int L_MOVZ=0; +int L_MTHI=0; +int L_MTLO=0; +int L_MTSA=0; +int L_MTSAB=0; +int L_MTSAH=0; +int L_MULT=0; +int L_MULTU=0; +int L_NOR=0; +int L_OR=0; +int L_ORI=0; +int L_PREF=0; +int L_SB=0; +int L_SD=0; +int L_SDL=0; +int L_SDR=0; +int L_SH=0; +int L_SLL=0; +int L_SLLV=0; +int L_SLT=0; +int L_SLTI=0; +int L_SLTIU=0; +int L_SLTU=0; +int L_SQ=0; +int L_SQC2=0; +int L_SRA=0; +int L_SRAV=0; +int L_SRL=0; +int L_SRLV=0; +int L_SUB=0; +int L_SUBU=0; +int L_SW=0; +int L_SWC1=0; +int L_SWL=0; +int L_SWR=0; +int L_SYNC=0; +int L_SYSCALL=0; +int L_TEQ=0; +int L_TEQI=0; +int L_TGE=0; +int L_TGEI=0; +int L_TGEIU=0; +int L_TGEU=0; +int L_TLT=0; +int L_TLTI=0; +int L_TLTIU=0; +int L_TLTU=0; +int L_TNE=0; +int L_TNEI=0; +int L_XOR=0; +int L_XORI=0; + + + + +//*****************MMI OPCODES********************************* +int L_MADD=0; +int L_MADDU=0; +int L_PLZCW=0; +int L_MADD1=0; +int L_MADDU1=0; +int L_MFHI1=0; +int L_MTHI1=0; +int L_MFLO1=0; +int L_MTLO1=0; +int L_MULT1=0; +int L_MULTU1=0; +int L_DIV1=0; +int L_DIVU1=0; +int L_PMFHL=0; +int L_PMTHL=0; +int L_PSLLH=0; +int L_PSRLH=0; +int L_PSRAH=0; +int L_PSLLW=0; +int L_PSRLW=0; +int L_PSRAW=0; +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +int L_PADDW=0; +int L_PSUBW=0; +int L_PCGTW=0; +int L_PMAXW=0; +int L_PADDH=0; +int L_PSUBH=0; +int L_PCGTH=0; +int L_PMAXH=0; +int L_PADDB=0; +int L_PSUBB=0; +int L_PCGTB=0; +int L_PADDSW=0; +int L_PSUBSW=0; +int L_PEXTLW=0; +int L_PPACW=0; +int L_PADDSH=0; +int L_PSUBSH=0; +int L_PEXTLH=0; +int L_PPACH=0; +int L_PADDSB=0; +int L_PSUBSB=0; +int L_PEXTLB=0; +int L_PPACB=0; +int L_PEXT5=0; +int L_PPAC5=0; +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +int L_PABSW=0; +int L_PCEQW=0; +int L_PMINW=0; +int L_PADSBH=0; +int L_PABSH=0; +int L_PCEQH=0; +int L_PMINH=0; +int L_PCEQB=0; +int L_PADDUW=0; +int L_PSUBUW=0; +int L_PEXTUW=0; +int L_PADDUH=0; +int L_PSUBUH=0; +int L_PEXTUH=0; +int L_PADDUB=0; +int L_PSUBUB=0; +int L_PEXTUB=0; +int L_QFSRV=0; +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +int L_PMADDW=0; +int L_PSLLVW=0; +int L_PSRLVW=0; +int L_PMSUBW=0; +int L_PMFHI=0; +int L_PMFLO=0; +int L_PINTH=0; +int L_PMULTW=0; +int L_PDIVW=0; +int L_PCPYLD=0; +int L_PMADDH=0; +int L_PHMADH=0; +int L_PAND=0; +int L_PXOR=0; +int L_PMSUBH=0; +int L_PHMSBH=0; +int L_PEXEH=0; +int L_PREVH=0; +int L_PMULTH=0; +int L_PDIVBW=0; +int L_PEXEW=0; +int L_PROT3W=0; +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +int L_PMADDUW=0; +int L_PSRAVW=0; +int L_PMTHI=0; +int L_PMTLO=0; +int L_PINTEH=0; +int L_PMULTUW=0; +int L_PDIVUW=0; +int L_PCPYUD=0; +int L_POR=0; +int L_PNOR=0; +int L_PEXCH=0; +int L_PCPYH=0; +int L_PEXCW=0; +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +int L_MFC0=0; +int L_MTC0=0; +int L_BC0F=0; +int L_BC0T=0; +int L_BC0FL=0; +int L_BC0TL=0; +int L_TLBR=0; +int L_TLBWI=0; +int L_TLBWR=0; +int L_TLBP=0; +int L_ERET=0; +int L_DI=0; +int L_EI=0; +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +int L_MFC1=0; +int L_CFC1=0; +int L_MTC1=0; +int L_CTC1=0; +int L_BC1F=0; +int L_BC1T=0; +int L_BC1FL=0; +int L_BC1TL=0; +int L_ADD_S=0; +int L_SUB_S=0; +int L_MUL_S=0; +int L_DIV_S=0; +int L_SQRT_S=0; +int L_ABS_S=0; +int L_MOV_S=0; +int L_NEG_S=0; +int L_RSQRT_S=0; +int L_ADDA_S=0; +int L_SUBA_S=0; +int L_MULA_S=0; +int L_MADD_S=0; +int L_MSUB_S=0; +int L_MADDA_S=0; +int L_MSUBA_S=0; +int L_CVT_W=0; +int L_MAX_S=0; +int L_MIN_S=0; +int L_C_F=0; +int L_C_EQ=0; +int L_C_LT=0; +int L_C_LE=0; + int L_CVT_S=0; +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +int L_QMFC2=0; +int L_CFC2=0; +int L_QMTC2=0; +int L_CTC2=0; +int L_BC2F=0; +int L_BC2T=0; +int L_BC2FL=0; +int L_BC2TL=0; +int L_VADDx=0; +int L_VADDy=0; +int L_VADDz=0; +int L_VADDw=0; +int L_VSUBx=0; +int L_VSUBy=0; +int L_VSUBz=0; +int L_VSUBw=0; +int L_VMADDx=0; +int L_VMADDy=0; +int L_VMADDz=0; +int L_VMADDw=0; +int L_VMSUBx=0; +int L_VMSUBy=0; +int L_VMSUBz=0; +int L_VMSUBw=0; +int L_VMAXx=0; +int L_VMAXy=0; +int L_VMAXz=0; +int L_VMAXw=0; +int L_VMINIx=0; +int L_VMINIy=0; +int L_VMINIz=0; +int L_VMINIw=0; +int L_VMULx=0; +int L_VMULy=0; +int L_VMULz=0; +int L_VMULw=0; +int L_VMULq=0; +int L_VMAXi=0; +int L_VMULi=0; +int L_VMINIi=0; +int L_VADDq=0; +int L_VMADDq=0; +int L_VADDi=0; +int L_VMADDi=0; +int L_VSUBq=0; +int L_VMSUBq=0; +int L_VSUBi=0; +int L_VMSUBi=0; +int L_VADD=0; +int L_VMADD=0; +int L_VMUL=0; +int L_VMAX=0; +int L_VSUB=0; +int L_VMSUB=0; +int L_VOPMSUB=0; +int L_VMINI=0; +int L_VIADD=0; +int L_VISUB=0; +int L_VIADDI=0; +int L_VIAND=0; +int L_VIOR=0; +int L_VCALLMS=0; +int L_VCALLMSR=0; +int L_VADDAx=0; +int L_VADDAy=0; +int L_VADDAz=0; +int L_VADDAw=0; +int L_VSUBAx=0; +int L_VSUBAy=0; +int L_VSUBAz=0; +int L_VSUBAw=0; +int L_VMADDAx=0; +int L_VMADDAy=0; +int L_VMADDAz=0; +int L_VMADDAw=0; +int L_VMSUBAx=0; +int L_VMSUBAy=0; +int L_VMSUBAz=0; +int L_VMSUBAw=0; +int L_VITOF0=0; +int L_VITOF4=0; +int L_VITOF12=0; +int L_VITOF15=0; +int L_VFTOI0=0; +int L_VFTOI4=0; +int L_VFTOI12=0; +int L_VFTOI15=0; +int L_VMULAx=0; +int L_VMULAy=0; +int L_VMULAz=0; +int L_VMULAw=0; +int L_VMULAq=0; +int L_VABS=0; +int L_VMULAi=0; +int L_VCLIPw=0; +int L_VADDAq=0; +int L_VMADDAq=0; +int L_VADDAi=0; +int L_VMADDAi=0; +int L_VSUBAq=0; +int L_VMSUBAq=0; +int L_VSUBAi=0; +int L_VMSUBAi=0; +int L_VADDA=0; +int L_VMADDA=0; +int L_VMULA=0; +int L_VSUBA=0; +int L_VMSUBA=0; +int L_VOPMULA=0; +int L_VNOP=0; +int L_VMOVE=0; +int L_VMR32=0; +int L_VLQI=0; +int L_VSQI=0; +int L_VLQD=0; +int L_VSQD=0; +int L_VDIV=0; +int L_VSQRT=0; +int L_VRSQRT=0; +int L_VWAITQ=0; +int L_VMTIR=0; +int L_VMFIR=0; +int L_VILWR=0; +int L_VISWR=0; +int L_VRNEXT=0; +int L_VRGET=0; +int L_VRINIT=0; +int L_VRXOR=0; diff --git a/Decode_XA.c b/Decode_XA.c new file mode 100644 index 0000000000..3bd53f4e70 --- /dev/null +++ b/Decode_XA.c @@ -0,0 +1,305 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ +//=== Modified by linuzappz +//============================================ + +#include + +#include "Decode_XA.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#endif + +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned long U32; + +#define NOT(_X_) (!(_X_)) +#define CLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} + +//============================================ +//=== ADPCM DECODING ROUTINES +//============================================ + +static double K0[4] = { + 0.0, + 0.9375, + 1.796875, + 1.53125 +}; + +static double K1[4] = { + 0.0, + 0.0, + -0.8125, + -0.859375 +}; + +#define BLKSIZ 28 /* block size (32 - 4 nibbles) */ + +//=========================================== +void ADPCM_InitDecode( ADPCM_Decode_t *decp ) +{ + decp->y0 = 0; + decp->y1 = 0; +} + +//=========================================== +#define SH 4 +#define SHC 10 + +#define IK0(fid) ((int)((-K0[fid]) * (1<> 4) & 0x0f; + range = (filter_range >> 0) & 0x0f; + + fy0 = decp->y0; + fy1 = decp->y1; + + for (i = BLKSIZ/4; i; --i) { + long y; + long x0, x1, x2, x3; + + y = *blockp++; + x3 = (short)( y & 0xf000) >> range; x3 <<= SH; + x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; + x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; + x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; + + x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; + x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; + x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; + x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; + + CLAMP( x0, -32768<> SH; destp += inc; + CLAMP( x1, -32768<> SH; destp += inc; + CLAMP( x2, -32768<> SH; destp += inc; + CLAMP( x3, -32768<> SH; destp += inc; + } + decp->y0 = fy0; + decp->y1 = fy1; +} + +static int headtable[4] = {0,2,8,10}; + +//=========================================== +static void xa_decode_data( xa_decode_t *xdp, unsigned char *srcp ) { + const U8 *sound_groupsp; + const U8 *sound_datap, *sound_datap2; + int i, j, k, nbits; + U16 data[4096], *datap; + short *destp; + + destp = xdp->pcm; + nbits = xdp->nbits == 4 ? 4 : 2; + + if (xdp->stereo) { // stereo + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } + else { // mono + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } +} + +//============================================ +//=== XA SPECIFIC ROUTINES +//============================================ +typedef struct { +U8 filenum; +U8 channum; +U8 submode; +U8 coding; + +U8 filenum2; +U8 channum2; +U8 submode2; +U8 coding2; +} xa_subheader_t; + +#define SUB_SUB_EOF (1<<7) // end of file +#define SUB_SUB_RT (1<<6) // real-time sector +#define SUB_SUB_FORM (1<<5) // 0 form1 1 form2 +#define SUB_SUB_TRIGGER (1<<4) // used for interrupt +#define SUB_SUB_DATA (1<<3) // contains data +#define SUB_SUB_AUDIO (1<<2) // contains audio +#define SUB_SUB_VIDEO (1<<1) // contains video +#define SUB_SUB_EOR (1<<0) // end of record + +#define AUDIO_CODING_GET_STEREO(_X_) ( (_X_) & 3) +#define AUDIO_CODING_GET_FREQ(_X_) (((_X_) >> 2) & 3) +#define AUDIO_CODING_GET_BPS(_X_) (((_X_) >> 4) & 3) +#define AUDIO_CODING_GET_EMPHASIS(_X_) (((_X_) >> 6) & 1) + +#define SUB_UNKNOWN 0 +#define SUB_VIDEO 1 +#define SUB_AUDIO 2 + +//============================================ +static int parse_xa_audio_sector( xa_decode_t *xdp, + xa_subheader_t *subheadp, + unsigned char *sectorp, + int is_first_sector ) { + if ( is_first_sector ) { + switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { + case 0: xdp->freq = 37800; break; + case 1: xdp->freq = 18900; break; + default: xdp->freq = 0; break; + } + switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { + case 0: xdp->nbits = 4; break; + case 1: xdp->nbits = 8; break; + default: xdp->nbits = 0; break; + } + switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { + case 0: xdp->stereo = 0; break; + case 1: xdp->stereo = 1; break; + default: xdp->stereo = 0; break; + } + + if ( xdp->freq == 0 ) + return -1; + + ADPCM_InitDecode( &xdp->left ); + ADPCM_InitDecode( &xdp->right ); + + xdp->nsamples = 18 * 28 * 8; + if (xdp->stereo == 1) xdp->nsamples /= 2; + } + xa_decode_data( xdp, sectorp ); + + return 0; +} + +//================================================================ +//=== THIS IS WHAT YOU HAVE TO CALL +//=== xdp - structure were all important data are returned +//=== sectorp - data in input +//=== pcmp - data in output +//=== is_first_sector - 1 if it's the 1st sector of the stream +//=== - 0 for any other successive sector +//=== return -1 if error +//================================================================ +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, int is_first_sector ) { + if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) + return -1; + + return 0; +} + +/* EXAMPLE: +"nsamples" is the number of 16 bit samples +every sample is 2 bytes in mono and 4 bytes in stereo + +xa_decode_t xa; + + sectorp = read_first_sector(); + xa_decode_sector( &xa, sectorp, 1 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + + while ( --n_sectors ) + { + sectorp = read_next_sector(); + xa_decode_sector( &xa, sectorp, 0 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + } +*/ diff --git a/Decode_XA.h b/Decode_XA.h new file mode 100644 index 0000000000..d363fb41cd --- /dev/null +++ b/Decode_XA.h @@ -0,0 +1,26 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct { + long y0, y1; +} ADPCM_Decode_t; + +typedef struct { + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/Docs/BetaTesters.txt b/Docs/BetaTesters.txt new file mode 100644 index 0000000000..3d15fb1458 --- /dev/null +++ b/Docs/BetaTesters.txt @@ -0,0 +1,13 @@ +Current PCSX2 Beta-Testers-Slaves :P : + +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever +Seta-San +Nave diff --git a/Docs/ChangeLog.txt b/Docs/ChangeLog.txt new file mode 100644 index 0000000000..3f34e3581d --- /dev/null +++ b/Docs/ChangeLog.txt @@ -0,0 +1,2742 @@ +[ Legend: ] +[ + Added feature ] +[ * Improved/changed feature ] +[ - Bug fixed (we hope) ] +[ ! Attention (Notes) ] + +ChangeLog: + v0.9: + * 06/28/06:[+] MAJOR CHANGE: All recompilers and memory code rewritten. + eeRec now does block analysis, constant propagation, liveness + analysis, mmx/xmm reg caching, etc. + vuRec is about 10x faster than older vurec. Both VU0 and + VU1 recs work and share the same code. + iopRec - does same as eeRec, except is simpler + Altogether, 3D scenes are 2-4x faster than 0.9 release. + (zerofrog) + + * 02/04/06:[+] VU0 Rec added, still buggy + [*] VU1 Speedups and fixes, needs more testing but seems better + [*] CDVD Timing Improved wait times for commands reduced. + [-] Misc eeRec bug fixes made + [*] Vif stalls greatly improved loads more games now work! + [*] Counters modified with gates and improved accuracy + [*] Cycle counting in EE/IOP done on branches to cut download + 2D speed up by over double! + [-] Misc VIF unpack fixes + [-] GIF Stalls should now work correctly + [+] Virtual Memory for Windows XP users, quicker than TLB + [*] Difference CPU options can be mixed and matched by users choice + [-] SIF communication fixed, games can now be booted via the bios (in most cases) + [!] Lots of other fixes have been made by due to lazyness we didnt document! :D + [!] This is the FINAL code for 0.9 enjoy! + (Refraction, ZeroFrog, Saqib) + * 15/02/06:[+] Multithreaded GS/Dual Core Support + (zerofrog) + * 17/01/06:[-] Some changes in CDVD tray status + (efp) + + * 16/01/06:[-] Fixed sticky flags. + [*] Implemented/Fixed a lot of vu functions in vurec. VuRec now properly checks for underflow/overflow + (zerofrog) + * 15/01/06:[-] Bug fixes in VU rec/interp (Ebit, xgkick). Added 24bit precision for VUs. + [*] Changed all math functions to use the C++ floating point versions. + (zerofrog) + * 14/01/06:[-] VU Flag fixes + double removal (it needed doing) from zerofrog + [-] Disabled an old PSX Counter hack that i left in some how! + [*] Changed SIF reg code to something simpler and less time consuming + (Refraction) + * 13/01/06:[*] Fixed mac update flags for vu interpreter. + (zerofrog) + + * 12/01/06:[-] Changed IPU.c, thread syncing issue fixed by zerofrog + [*] Altered SBUS so it is triggered on PSX dma + [*] Removed a load of IOP hacks, should improve compatability in some cases + [!] A lot of changes have been made since 05/09/05 but weve lost track, whoops + (Refraction Saqib zerofrog) + + * 05/01/06:[*] Added GSreadFIFO2 for faster reads from GS. + [-] Fixed the multi-threaded IPU and added sync primitives for interrupts and DMA. + The green squares should be gone too. + (zerofrog) + + * 05/09/05:[-] Fixed VU-Rec crash if the pc overflowed the vumem, thanks to fumofumo! + [*] New Icon for 0.9 made by CKemu + [+] Vsync rate now selectable, current Vsync speed is default but less compatable in + some cases, option selects real vsync speed, syncs sound correctly. + (Refraction) + + * 03/09/05:[-] IOP rec & VU0rec fix, x86ptr being set in the wrong place, also a couple of vu-rec op fixes + thanks to fumofumo on irc. + [-] Slowed VSync down to actual speed, so sound isnt half the speed of the graphics, + a few more changes to counters as well, BOR works again, just slower ;p + (Refraction) + + * 30/08/05:[-] Few more changes to the counters, seems much better again, last fix killed stuff + [-] VSync rate now actually changes between PAL and NTSC, before it was stuck in NTSC + [-] Couple of changes in VIF + * 24/08/05:[-] Readded setting of Done on VIF1 TTE, added the same on VIF0 + [-] Applied VIF1 FBRST fix to VIF0 too + [-] Fixed problem causing Beats Of Rage to skip and altered slow sound prob again. + (Refraction) + + * 23/08/05:[-] Did some more timing fixes, they should be a LOT more compatable now + [-] Small change to FBRST, was causing crashes if VIF was finished. + [+] Added counter copy to hold on SBUS interrupt + (Refraction) + + * 21/08/05:[-] Few fixes in the eeRec, shouldnt crash on Kingdom Hearts now, Thanks to fumofumo! + [-] Fixed a bug in FBRST and Vif1, altho theres still an interrupting problem somewhere :/ + [-] Int VU now uses Single Precision (its faster) with no loss of graphics. + [-] Made sure MAC, CLIP and STATUS flags are all located on VU0. + [*] Enabled linuz's SSE unpack code, gives a nice little speed boost, works ok :) + [-] VU execute blocks limited to 128, seems a little faster, no loss of graphics, seems + to fix a few looping infinately issues (VU not breaking) (GiGaHeRz) + [-] Hack removed on TLBP, should hopefully work ok, doesnt seem to break anything (GiGaHeRz) + [+] Added SPU2 hack, should fix some games, not compatable with videos tho. removed fast dvd + [-] More counter stuff, also added gating to IOP counters, not totally sure on it. + [-] Added a couple of checks in VU & eeRec to make sure the constant registers werent overwritten + [-] Temp fix for the dma alignment error on GIF + [-] modified dma timings, qwc / BIAS could mess up if qwc = 1 + [-] Singled out some problematic VU-Rec ops that cause FFX to hang and borkey graphics. + (Refraction) + + * 12/08/05:[*] Few more timing things, music shouldnt be slow anymore on games and cleaned up + counters a bit. + [+] Added SBUS register logging on IOP side + [-] Temp fixed a MAC flag problem in vu-rec till linuz sorts it properly + [*] Committed new logo, nice job CKEmu ;) + [*] Vu-Rec now supports non SSE2 processors thanks to kekko for the changes! + (refraction) + + * 05/08/05:[+] Added faster Cd/DVD reads to the Advanced options (Refraction) + [-] The previous DVD/CD change by ref was just a hack, so i commited the old + version again + [-] I've commented out RECOMPILE_VUMI_LOADSTORE on iVUmicro.h, instead + of commenting it out in iVU1micro.c as ref did on last update, + that way is better until i fix the real problem + [*] Improved vuDIV for .x to .x cases + [+] Added PEXTRW/PINSRW + (linuzappz) + + * 05/08/05:[-] Fixed a couple of VU-Rec ops, swapped some over to the interpreter to fix 2d + (thanks to fumofumo for the tipoff) + [-] Yes more timing stuff :P think its as compatable as its going to get now. + [*] DVD/CD reads now considerably faster, some loading times down by 1600%!!! + Compatability still good :) + [-] Fixed a bug in 128bit hardware reads + [-] Fixed a bug i made in VU which messed graphics up eg Frequency and Sega Tennis + (refraction) + + * 04/08/05:[-] More IOP/EE timing fixes, Thanks for the info linuz + [-] Vsync speeds shouldnt be as insane as they were, the target was set as 1/4 the rate + instead of 1/2! + [!] 32bit timer interrupt checks arent working properly eg. overflow only works + when checking if they are equal, on target only works on overflow :/ but the checking + method which was used in SafeIOP is more accurate. + (refraction) + + * 03/08/05:[-] Fixed FTOX in VUrec + (linuzappz) + + * 31/07/05:[-] Reverted to old Branchtarget's, seems to stop the RecUNKs + [-] Fixed the timing a bit between IOP & EE, shouldn't need SafeIOP anymore :D + [-] Removed Pointless While loops on GIF & SPR, also fixed condition where SPR0 + couldn't use destination chain mode + [!] Gating on the IOP needs checking/completing, i have no docs on it so + i can't check the values for it, they seem different to EE :/ + [-] Removed GS Stall checking on GIF, could have caused it not to send data. + [*] Added code for faster V4-32 unpacks when CL == WL + [*] x86 code kept in int format for rec instead of U8 to INT conversion (GiGaHeRz) + (refraction) + + * 21/07/05:[-] Fixed setting of the Double Buffer + [-] Fixed the Branchtarget's for R3000A and R5900 + [*] Altered some stuff in vuflags, seems to give a speed boost :P + (refraction) + + * 18/07/05:[-] Removed some useless & 0xffff on Hw.c + [-] Reverted Sif changes to the old code, + gotta speak about this with refraction + [+] Added VIF1_STAT at vif1Write32, to handled the FDR bit + [-] VIF1 now clears qwc with "from memory" transfer + (linuzappz) + + * 17/07/05:[-] Fixed a bug in VIF where done could be unset + [-] Fixed a couple of bugs in VU + [*] Rewrote SIF0, seems to be a bit more compatable as well + as more readable + [-] Altered the loops for vu(1/0)exec, seems to fix some graphics + without comprimising compatability + (refraction) + + * 12/07/05:[-] Fixed VIF stop on stall occurance (refraction) + [-] Added two common funcs for source chain dmas + [-] Fixed REFE and END (even once again) in dmas + [-] Fixed interrupt i bit issue in Vif1 (on multiple i bits) + (linuzappz) + + * 08/07/05:[-] MFIFO now wraps around the ring buffer when it's full, + in both GIF/VIF1 + (linuzappz) + + * 06/07/05:[-] Bug in DIRECT/HL caused vif errors + [-] Recomitted old VIF0 IRQ stuff, seemed to cause problems + (Refraction) + + * 05/07/05:[-] Fixed IRQ setting for VIF0 transfers (Refraction) + [*] Removed Call/Ret from SPR1, not used (Refraction) + [+] Added some more comments to DMA stuff (Refraction) + [-] Reimplemented the old vifunpack code, since saqib's one + had problems 'in pieces' transfers + [-] ElfHeader now loads the data though the program headers only + [-] Removed tadr+= 16 on refe/end on dmas + [!] I'll start commenting more the code from now on, so it'll + be easier for us to understand every part of pcsx2, others + pls do the same kthx + (Refraction-linuzappz) + + * 02/07/05:[-] Added saqib vif fixes + [-] Fixed Stall canceling stat bits (VIF_STAT_INT) + [-] Fixed Stall bits clearing + (Refraction-saqib-linuzappz) + + * 29/06/05:[*] iR3000A now has defines same as iR5900.c + [+] Added PSXCNT_LOG + (linuzappz) + + * 28/06/05:[+] Added InterlaceHack (usefull for Dinasty Warriors 3) + [+] Added SafeCnts flag, which makes very accurate iop counters, + but they make pcsx2 slower + [+] Added FastIopClk which sets the PsxClk to 86864000 + [!] There are sorta hacks and will go away in time when i figure + out how to really fix them + (linuzappz) + + * 28/06/05:[+] Added SIO plugin specs. Should be followed by compatible plugins :P + (Florin) + + * 22/06/05:[-] Console supports colors ;) + (linuzappz) + + * 19/06/05:[-] Fixed D/T flags (added interrupts) at VU0/1 + (linuzappz) + + * 18/06/05:[-] Rather small fixes to last update in vif, replaced cyclenum + with _vif->cl, also fixed a timing issue in vif0 + (linuzappz) + + * 14/06/05:[-] Alot of bugs fixed in VIF. Masking was not correct so was + filling write. VIF0 was incorrect. The VIF0 Fifo was always being set to 0. + [-] dmaSPR1 now handles Transfer Tag option. + (saqib and Refraction) + + * 31/05/05:[-] Fixed UNPACK's with masking + (linuzappz) + + * 29/05/05:[-] Fixed a few small timing issues with VIF1 + [-] Refixed end source chain tag to add 16 to tadr + (linuzappz) + + * 28/05/05:[*] Uncommented GS dma irq code + [-] Fixed some switch cases at iVUmicro.c + [-] Tested/Fixed DIS_S/MAX_S/MIN_S at iFPU.c + (linuzappz) + + * 28/05/05:[*] removed CVT_S regcaching from iFPU.c. That doesn't seem to work properly :~ + [*] Added MAX_S , MIN_S to reg caching iFPU.c . Not tested but should work + (shadow) + + * 28/05/05:[+] Added PNOR and impoved a few more MMI opcodes + [+] Few more opcodes to ix86_sse.c as well + (shadow) + + * 26/05/05:[+] added emulated hardware cd/dvd sector decryption routines + (should make the playstation2 logo display correctly now amoung other things) + [-] fixed cdvdReadKey to get correct args sent to it, also behaves a little differently depending on args + (loser) + + * 26/05/05:[*] fixed a silly bug in iMMI.c pmaxh,pminh opcodes + [*] optimized PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + [*] few more addes to ix86_sse.c . Linuz seemed to discovered new opcodes :P + (shadow) + + * 25/05/05:[+] Few opcodes added in ix86_sse.c .Few of them still needs recheck (shadow- Gabest) + [*] Added the following SSE,SSE2 opcodes to iMMI.c . + paddub,padduh,paddh,pcpyld,pmaxh,pminh,paddsb,paddsh,psubsb,psubsw,paddb,paddw,psubsb,psubsh + psubb,psubb,psubh,psubw + [*] More opcodes in SSE2 . PCPYUD,PSRLW,PSRLH,PSRAH,PSRAW,PSLLH ,PSLLW ,PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + (shadow) + + * 24/05/05:[*] PSXCLK now can be changed at the ini, defaults + to the right value (36864000) if it's 0 anyways + [-] Fixed bug at Interpreter.c for sstates + (linuzappz) + + * 23/05/05:[-] fixed a bug in iMMi.c PADDSD,PSUBSD doesn't exist in ix86 (who added them?) + [*] Added a new prefix in ix86_SSE opcodes, it is now more clear to understand what each opcode do + that also helped to find that linuz had added an SSE2 instruction in iFPU.c bad linuz ;P + [-] PSMAXSW,PSMINSW was writing to a XMM register (the SSE version writes to MMX register) fixed.. + [+] a few more SSE2 instructions needed for iMMI.c added in ix86_sse.c . + Linuz code them properly pls ;) + (shadow) + + * 23/05/05:[+] Added Devc++ 4.9.9.2 project files for compiling mingw32 with IDE :) + [-] Added a few missing defines + [!] still my project file can't make as fast exe as linuz's sse build. can't figure why yet + the problem should me around Makefile.win :~ + (shadow) + + * 21/05/05:[-] More PS1 compat fixes + [!] Seems the GPU->GS is done by the PS1DRV, gotta find out more + (linuzappz) + + * 19/05/05:[+] PS1 games kinda boot now as well ;) + (linuzappz) + + * 16/05/05:[-] Misc GUI fixes + (linuzappz) + + * 15/05/05:[-] More FPU regcaching stuff + [!] Finally changed version to 0.9 :D + (linuzappz) + + v0.8: + * 10/05/05:[-] Added some more code for FPU regcaching, still unused + [!] Code is closed today until release, only bugfixes now + (linuzappz) + + * 08/05/05:[-] More fixes/improvemets to VUrec/iFPU + (linuzappz) + + * 07/05/05:[-] COP2 now is recompiled when VUrec is enabled + (linuzappz) + + * 05/05/05:[-] Fixed a rather small bug in VIF1 unpack + [-] VU random functions are more correct now, thx goes to _Riff_ and saqib + [-] Sio arranged better for sstates + [*] Modified "FireWire" syms to "FW" + (linuzappz) + + * 04/05/05:[-] Timings in VIF1 should be more accurate now + [-] Fixed bug in the elf loading filter + (linuzappz) + + * 02/05/05:[*] recommited the old reccop2.c (shadow) + + * 02/05/05:[-] Fixed bug in REF/REFS dma at VIF1/GS MFIFO + (saqib) + + * 02/05/05:[*] Cpudialog will disable the checkboxes if the requested features not found + (shadow) + + * 01/05/05:[*] Created a new <> folder to clean up some stuff in the existing interface + Folders became better now and included project files only for vcnet2003 so far... + [*] Moved all patchbrowser source to patchbrowser.c and added language support for it + [*] CpuDialog is now At CpuDlg.c . Redone the Dialog a lotta better ;) + [*] The remaining console,thread,patches configure are now part of the main menu + [*] Organize cpudetection code a bit better. Cpudetection is now done in winmain.c + (shadow) + * 01/05/05:[*] Even more VUrec stuff + [+] Added some more Stats.c info per frame + [-] Fixed some MFIFO bugs remaining + (linuzappz) + + * 30/04/05:[*] More work on VUrec, flags are somehow implemented, PSHUFD is now + used to unpack XYZW/IQ stuff and bug fixes as well :) + (linuzappz) + + * 29/04/05:[-] Updated VIF0 code as VIF1 + [-] VIF1 doens't clears str on MFIFO (saqib) + [-] Fixed some MFIFO bugs in both GS/VIF1(saqib) + [*] Cleaned up dma## functions + (linuzappz) + + * 28/04/05:[-] end source chain tag seems not to touch tadr + [-] Vif1 dmaIrq seems ok, need to test it more tough + (linuzappz) + + * 26/04/05:[+] Added BC1 ops at rec + [+] Started some optimizations for UNPACK + [-] Skipping vif mode was still a bit buggy, seems ok now + (linuzappz) + + * 25/04/05:[*] VIF1 dma is kinda more asynchonous now + (linuzappz) + + * 22/04/05:[+] Added some cache code, not used by default, + it's just for testing atm + (linuzappz) + + * 21/04/05:[-] Readded SysPrintf for Cd/DvdReads + [-] Fixed NReady busy stuff, thx to loser + (linuzappz) + + * 19/04/05:[-] More VUrec refixing/work + (linuzappz) + + * 18/04/05:[+] added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose + to the cdvd plugin definitions + [*] changed CDVDgetType to CDVDgetDiskType + [-] fixed NVM (eeprom) access from cdvd stuff + [+] added reading of mecha version from an external file + [-] fixed raw dvd sector readng for dvd9 discs (otp and ptp) + [+] added hw-reg read/write for DecSet register 0x1f40203A + [+] made cdSeek change the current cdvd sector + [*] incremented cdvd plugin version and brought cdvd plugins in cvs up to date + (loser) + [-] __WIN32__ should not be used over PS2Etypes.h, + __MSCW32__ or __MINGW32__ must be used there + (linuzappz) + + * 16/04/05:[-] xyzw stalls was kinda wrong ;P seems ok now + [-] Fixed a bit vurecs + (linuzappz) + + * 16/04/05:[+] Added GSsetCSR + (saqib-linuzappz) + + * 14/04/05:[-] Fixed some small bugs over VUops.c for the regsNum stuff, + thx goes to saqib + [-] Really fixed skipping vif this time :P + [-] Fixed DIV/RSQRT exceptions (saqib-linuzappz) + (linuzappz) + + * 13/04/05:[-] Fixed skipping write mode at Vif + [-] Fixed unpack overflowing + (linuzappz) + [-] updated all visual studio project files to have the correct source/lib/includes + also removed unused dirs and files. now even 'debug config' will build ok :) + (loser) + + * 10/04/05:[-] Fixed stalls for VF regs, xyzw must be handled separatedly + (linuzappz) + + * 04/04/05:[-] Kinda reworked VU MAC flags, also fixed RSQRT neg prob, thx to Riff/saqib + [-] Fixes to VifDma cl/wl stuff + (linuzappz) + + * 03/04/05:[*] Modified a bit how branch works on VUs + (linuzappz) + + * 02/04/05:[-] Some fixes to VU flags/pipelines + (linuzappz) + + * 30/03/05:[*] Cleaned up a bit writes to VIFX regs + [-] Fixed a small bug in vif1 stalls + [-] Commented readclock win32 code at CDVD.c + [-] Fixed two small issues with branches in interp + (linuzappz) + + * 29/03/05:[*] Added some fixes from LDChen to hConsole/WM_PAINT stuff + [*] Modified GetToc stuff in cdvd to support dvds + [*] cdvdTD uses lsn now + (linuzappz) + + * 28/03/05:[+] Added placetopatch == 1, which means patches will be applied every vsync ;) + (linuzappz) + + * 27/03/05:[*] Improved cpu detection for Amd's 64 using BrandID. Most of the models should be + detected correct now (at least my cpu does ;P) (shadow) + + * 24/03/05:[-] Fixed ISUBIU :D + [-] Some fixes to flags, status was fecked, now seems better + [-] Commented the GS dma IRQ again, seems to cause more probs, will + fix it later + (linuzappz) + + * 21/03/05:[-] Fixed VIFX_CODE reg + [+] Added previous normal vu fixes to vurec + [*] Added EFU pipeline to VUmicro, kinda untested + [-] Hopefully fixed GS dma IRQ + (linuzappz) + + * 21/03/05:[-] Fixed cdReadKey function to emulate correctly. Now games should boot using + Execute with non Modded Bios. + (auMatt & Loser) + + * 20/03/05:[-] Started reg caching for VUrec ;D + [*] Rearrenged a bit rec32/64, added a common 'x86' dir + (linuzappz) + + * 18/03/05:[-] VU1micro was being executed instead of VU0, bad linuz bad :P + [-] Fixed VU's JR/JALR/BAL :D + (linuzappz) + + * 17/03/05:[-] Cleanup/speedup/fixup from last fixes :P + [-] VIF0 has no from mode ;) + (linuzappz) + + * 16/03/05:[*] Added some more debug info to CDVD + (auMatt) + + * 15/03/05:[*] Added an evil vuDouble function to convert from vu float format + to ieee 754 format ;) + [-] Reworked MAX/MINI + [+] Added experimental work for VU pipelines + (linuzappz) + + * 14/03/05:[-] Added the pipelines VU1 bug to VU0 + (linuzappz) + + * 12/03/05:[-] Fixed some pipelines bug within VU1 + (linuzappz) + + * 10/03/05:[-] Fixed small bug over VIF1 dma FIFO + (linuzappz) + + * 08/03/05:[-] Fixed vu flushing over vuExecMicro + (linuzappz) + + * 06/03/05:[-] Fixed UNPACK V4_5 with mask + (linuzappz) + + * 04/03/05:[-] Small fixes to VUrec + (linuzappz) + + * 01/03/05:[+] Added new VS2005 sln and .vcproj to build the 32bit version of + pcsx2 in VS2005 Beta1 (You have to use different projects to build) + [*] Changed some of the files to make them compile in VS2005. + (GoldFinger) + + * 23/02/05:[-] Commented hack at VSync + [+] Added interleave mode for SPR + (linuzappz) + + * 20/02/05:[*] Changed IRQ defines to functions + [-] VIF irq by vifcode seems ok now + [+] Added offset/difference with mask UNPACK modes in vif + [-] SPR1 was transfer /4 the size it should have :/ + (linuzappz) + + * 16/02/05:[-] Fixed some VPU-STAT related issues + [+] 'sstates' dir is now created at init + (linuzappz) + + * 15/02/05:[+] Another DNAS by nachbrenner + (linuzappz) + + * 14/02/05:[+] Added offset/difference UNPACK modes in vif + (linuzappz) + + * 14/02/05:[*] 64bit rec back to x86-64 better this way + [*] Updated vsnet2005beta1 project files to compile with x86-64 dir + [*] Added a few pragma warnings disable to a few files to correct some silly vsnet2005beta1 + warnings (blah MS deprecated stdio pffff) (shadow) + + * 10/02/05:[-] Fixed bug in CDVD_findfile + (linuzappz) + + * 09/02/05:[*] GSvsync is now called on the vsync start + (linuzappz) + + * 08/02/05:[*] QWC is set to 0 after a normal transfer in GS/SPR1/VIF1 + and MADR is increased qwc*16 as well + (linuzappz) + + * 07/02/05:[*] Changed a bit the CPU dialog. Now it is better i guess :) . Linuz update the pcsx2.po again pls :D + [*] Added a __VCNET2005__ definition cause vcnet2005beta1 doesn't support inline asm.. + That only effects Cpudetection.c and Gte.c (not much since it has c code instead to use). + Cpudetection must be written on ml64 to be useable on vcnet2005. + [*] Added prelimary vcnet2005beta1 project files. gettext disabled cause we still doesn't have a + 64bit version for it + [*] Small fixes around and wholaaa i produced the first buggy pcsx2_64bit.exe :) (shadow) + + + * 07/02/05:[+] Added another DNAS version thx to Nachbrenner + [-] Fixed SPR0 chain mode + [-] Fixed intc/dmac interrupts that gets cleared right away + [-] Cleaned up langs a bit, only spanish works so far now + [+] Added 1f402007 reg, "BREAK", still not really handled ;P, + thx to matt + (linuzappz) + + * 31/01/05:[-] Disabled recompile functions recBGEZ() and recBLEZ() from iR3000.c . That will make + recompiler not to crash after the players selection screen in Virtua Fighter 4. Thanks + to JayteeMaster for bug tracing it ;) (shadow) + + * 30/01/05:[-] Fixed some more bugs in IPU, some streams had a few problems, now they are ok. + Quality of ipu playback also improved(thanks JayteeMaster for pointing it out) + (asadr aka saqib) + + * 26/01/05;[*] Merged a big part of linuz's amd64 rec to the normal rec (shadow) + + * 25/01/05:[-] Finally fixed IPU. Mpegs and IPU streams run + so do PSS files.Some fixes to MMI and Interpreter (asadr) + + * 23/01/05:[-] Fixed vurec crash on pcs that doesn't support SSE2 + [*] General cleanup on ix86-32 rec. Goldrec removed since no progress has been made + lately (shadow) + + * 20/01/05:[+] Added x86-64 rec, still unclean, but i'll leave for holidays this + saturday, so ^^ + (linuzappz) + + * 19/01/05:[-] Fix for end chain mode at vif, still gotta check it + (linuzappz) + + * 16/01/05:[-] Lots of fixes to VUmicro, thx to Refraction for pointig out + some bugs ^^ + [*] Commited ix86 changes for x64 + (linuzappz) + + * 13/01/05:[-] WriteNVM now takes address in param[1], thx to auMatt + (linuzappz) + + * 06/01/05:[-] Fixed long types at VU.h + [-] Removed memLUT decl + [!] Notice long is 8bytes long in amd64, so we should + stick to the u32/s32 types instead of using long pls :) + (linuzappz) + + * 06/01/05:[-] Fixed SBUS IRQ at iop + [-] dmaGetAddr now uses memLUTR + (linuzappz) + + * 05/01/05:[*] Changed some stuff for amd64, still more to come + [+] Added more memRead/Write funcs for speed + [-] Fixed some iVUmicro bugs + [-] Fixed QFSRV/MTSAH/MTSAB + (linuzappz) + + * 03/01/05:[+] Implemented MFLAG for VU0 + [-] Vsync is now genereted on boths cpus at the same time + (linuzappz) + + * 03/01/05:[-] Commented dma irq stuff, fecks some games, gotta recheck that + (linuzappz) + + * 22/12/04:[-] Fixed bug in branch address in vus + (linuzappz) + + v0.7: + * 18/12/04:[*] Added GSread8/16/GSwrite8/16, GSgifTransfer1 now has two args, + added the addr and pMem points to the VU1 mem + (linuzappz) + + * 16/12/04:[*] Pofis improved his Patchbrowser (shadow) + + * 06/12/04:[-] Fixed Langs support for win32 + (linuzappz) + + * 06/12/04:[*] Added support for 1.90 Bios NVM. + (auMatt) + + * 06/12/04:[+] Added Patch Browser for win32 . Made by Pofis (shadow) + + * 05/12/04:[*] NVM always loads rom %Bios%.NVM + [*] Cd/Dvd Reads are now again displayed on console, + that is very helpfull for testing :) + (linuzappz) + + * 28/11/04:[-] BC2T/F/TL/FL also check for VU1 to be stopped + [-] VU1 memory is masked on micro load/store instructions, + dunno yet about VU0, gotta test ;) + (linuzappz) + + * 26/11/04:[-] VU D/T flags are handled now (kindaof :P). + (linuzappz) + + * 20/11/04:[-] RTC timezone fixed (gigaherz) + + * 19/11/04:[-] Fixed vu branch negative overflows + (linuzappz) + + * 17/11/04:[*] Fixed some stuff in logging so now + -Memcards sysprintf messages Are now MEMCARDS_LOG define and enable with PAD_LOG + -Cdreads Dvdreads are now in CDR_LOG + -Vus Overflow enable from CPU_LOG + That means less logs at runtime and no more complains from nasty betatesters :D (shadow) + + + * 17/11/04:[*] fixed linuz bug in naming the memcards different in 2 different places + Memcards now are Mcd001.ps2 and Mcd002.ps2 in emu and McdDialog (shadow) + + * 16/11/04:[-] Fixed NVM File Load and Creation. Defaults to BIOS name als now. + (auMatt) + + * 15/11/04:[+] Added another DNAS at Misc.c. + (nachbrenner) + + * 14/11/04:[-] VU0/1 reset shouldn't reset the micro memory. + [*] Commented the LT_OpcodePrintTable call on Interpreter.c, + for speed :) + (linuzappz) + + * 12/11/04:[-] Second MCD works fine now. + (linuzappz) + + * 11/11/04:[-] Finally fixed SIF1 bug :D:D + (linuzappz) + + * 10/11/04:[+] Added MingW32 support ;). + (linuzappz) + + * 10/11/04:[-] Fixed NVM loading/reading/writing and also fixed v12 NVM issues. + (auMatt) + + * 09/11/04:[+] Added BiosVersion var. + [*] Sif stuff now gets saved over sstates. + (linuzappz) + + * 09/11/04:[-] Fixed bug in ModelID code in CDVD + (florin-auMatt) + + * 07/11/04:[-] Fixed bug that caused to interrupt twice before + handling the first interrupt. + (linuzappz) + + * 05/11/04:[-] Small fix for broken elfs. + (linuzappz) + + * 04/11/04:[-] CDVD was interrupting dma too much :P. + (linuzappz) + + * 03/11/04:[*] Added FREEZE_SIZE. + (gabest-linuzappz) + + * 03/11/04:[+] Added a couple of DNAS at Misc.c. + (nachbrenner) + + * 02/11/04:[+] Added hack for QFC in GS ;). + (linuzappz) + + * 01/11/04:[+] Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2. + (linuzappz) + + * 31/10/04:[-] Fixed v12 bios running. + (auMatt) + + * 30/10/04:[-] Fixed v9-v10 bios running. + (auMatt) + + * 28/10/04:[-] Really fixed SIF SMFLAG/MSFLAG :P:D + (linuzappz) + + * 28/10/04:[-] Fixed MCDS :D + (asadr) + + * 26/10/04:[*] Added rom2/erom support + (auMatt/linuzappz) + + * 23/10/04:[*] Added/Fixed Model Number Reading + (auMatt/Florin) + + * 18/10/04:[-] Fixed SIF SMFLAG/MSFLAG, needs testing tho + (linuzappz) + + * 06/10/04:[*] More BIOS detection added.(auMatt) + + * 04/10/04:[-] Fixed EXL bug + [-] Fixed SIF0/1 when fifo got filled up + (linuzappz) + + * 01/10/04:[-] CdReadConfig/CdWriteConfig now uses NVM ^^ + [!] Bios configurations now gets saved/loaded from NVM (nvm.raw) + (linuzappz) + + * 1/10/04:[+] Started coding the memcard manager. Far from finish but will be better soon :D + [*] Change settings . Default memcard is now a ps2 memcard. (shadow) + + * 30/09/04:[-] Newer bios will now work with pcsx2. Pads fixed, more + compatibility. (asadr) + + * 27/09/04:[-] VU0/1 Reset hopefull fixed + (linuzappz) + + * 16/09/04:[*] NVM now is readed/written from nvm.raw. + [-] ReadILink/GetMecaconVersion are really implemented ^^ + (auMatt-linuzappz) + + * 15/09/04:[*] Rewritten LoadConfig-SaveConfig to use ini instead of registry. + [*] Removed DeleteRegistry button. For obvious reasons :D (shadow) + + * 15/09/04:[-] Pads finally fixed - Fixed PADwin Plugin Required! + Updated stuff at PsxSio2.c and Sio.c (Pad Hack still + there but won't be used) asadr + + * 13/09/04:[+] Added an option for setting the main thread priority, usefull at work :P + (linuzappz) + + * 13/09/04:[*] Fixes to SCMD's (auMatt) + * 02/09/04:[*] Finally commited asadr's IPU changes + [-] Fixed small bug in memory dump for win32 + (linuzappz) + + * 30/08/04:[*] Added Deci2 Call back into the Interpreter.c for printf.(auMatt) + + * 18/08/04:[*] fixed finaly the IOP disasm. Should be correct now... + [+] for stuff for amd64 porting.notice that pcsx2_2003_amd64 project just check for 64bit + portability.Can't produce 64bit exe yet.. (shadow) + + * 15/08/04:[-] fixed the IOP-EE disasm problem.(for ppl with vc != 2003 you must include + DisR3000asm.c and DismAsm.h in your project files) + [!] Still have to finish the correct IOP disasm :D + [+] Added small framework for x86-64. Still nothing that useable :D (shadow) + + * 04/08/04:[-] PadHack now works again :) + [-] Sio2 now supports states again + (linuzappz) + + * 02/08/04:[*] F2 will print the selected state on the console + [*] Added overflow messages for ISW/ILW/ILWR/ISWR + [*] FBRST should reset the vus when VU0 Reset/VU1 Reset + bits are set, but i don't really know have much it's + resetted :P + (linuzappz) + + * 30/07/04:[-] Vif1 MPG lacked a flush + (linuzappz) + + * 28/06/04:[+] Added GSprintf, GSgetDriverInfo and PADgsDriverInfo + [+] Deci2Call 0x10 gets printed ;) + [-] Some fixes to CDVD reading + (linuzappz) + + * 24/06/04:[-] Fixed some bugs over interrupts and + exceptions + (linuzappz) + + * 22/06/04:[-] Couple of bugs fixed over IPU1 dma + [-] psHu32(INTC_STAT) changed to INTC_IRQ + (asadr-linuzappz) + + * 16/06/04:[-] Counters regs are returned in 16 bits + [+] Also added them for hwRead16 + [-] Counter only resets when writing to the mode reg + when the value & 0x3ff differs from the actual mode + [-] Fixed BCR interrupting for CDVD ;) + (linuzappz) + + * 14/06/04:[*] Enabled SSE Vif at i386.asm + [*] Added florin's work over mcds, still needs + a cleanup :) + (linuzappz) + + * 10/06/04:[*] CSRr is OR'd with 0x8 always over VSyncEnd + (linuzappz) + + * 08/06/04:[*] VU pointer gets aligned now + (linuzappz) + + * 07/06/04:[*] vuJALR now uses _Fs_*8 + [*] VSync now interrupt for INTC_STAT & 0x1 + [!] Based of debugging Aura for Laura :) + (linuzappz) + + * 07/06/04:[*] Detection for Chinese Bios. + (auMatt) + + * 04/06/04:[-] Cleaned a bit VIF1transfer, and now when + DIRECT/DIRECTHL cmd is misaligned it skips it + [*] Added USBirqHandler, USB specs v2 now + (linuzappz) + + * 04/06/04:[-] VU1 regs now are mapped to VU0 mem + (linuzappz) + + * 02/06/06:[*] finished most of the iops disasm works :P + [*] increase the firewire reg size . seems there are more regs ;p (shadow) + + * 25/05/04:[-] Fixed big stupid bug in counters ;P + Now they're accurate + (linuzappz) + + * 25/05/04:[*] Included new BIOS detection 'P'. For Free and Public BIOS Images. + (auMatt) + + * 20/05/04:[*] BCR now decrements for each cdvdReadSector, thx to Roor + (linuzappz) + + * 18/05/04:[*] Removed PsxBios2.c/h, and cleaned Irx funcs from ElfHeader.c/h + [+] Added cpuTestHwInts/cpuTestINTCInts/cpuTestDMACInts + [+] More work over mcds + [!] Now cpuBranchTest doesn't checks for irqs + (linuzappz) + + * 17/05/04:[-] Fixed bug psx counters, thx gold + (linuzappz) + + * 15/05/04:[+] Added IOP disasm in the debugger... + [!] Not yet finished and i disasm using R5900disasm atm. I will code it correctly soon (shadow) + + * 12/05/04:[*] More optimizations to the FPU rec + [*] BIAS was commented over Counters.c :/ lol + [-] Disabled EMMS_TRACE, it's buggy, dunno why tho + (linuzappz) + + * 11/05/04:[*] Now Saving/Loading FPU CW only for the ops that really need it + [*] Added some optimizations to jumps over rec + [*] Added LQC2/SQC2 + (linuzappz) + + * 08/05/04:[-] Fixed states loading/saving from the menu + (linuzappz) + + * 03/05/04:[*] Uncommented the sio2 1d100 hack + (linuzappz) + + * 3/05/04:[+] started reorganize the src. Lotta unneccesary stuff removed(like HLE) and lotta + organized. still needs a lot of work to clean but it's a start (shadow) + + * 02/05/04:[+] Added D3/D4 defines at Hw.h + (linuzappz) + + * 1/05/04:[+] Added a Delete Registry Button. It deletes pcsx2,gssoft settings + (shadow) + + * 30/04/04:[-] Small bugfix for cpu speed detection, thx to Rainer Aglas + (linuzappz) + + * 27/04/04:[+] Implemented ReadNVM/WriteNVM, untested though + (linuzappz) + + * 15/04/04:[-] SPUdma timings changed to 80, thx _Riff_ + (linuzappz) + + * 13/04/04:[*] Several changes for IPU + [+] IsBIOS now belongs to Misc.c + (asadr-linuzappz) + + [*] Dev9Null/USBLinuz/FireWire Plugins Configure now shows + Message. + [*] Configure Menu Shows USB and FireWire Options. + (auMatt) + + * 12/04/04:[-] Fixed SPU2async cycle, was getting reseted wrongly, + thx _Riff_ + [+] Added SPU2irqCallback + (linuzappz) + + * 08/04/04:[-] Unhacked sio2 for 1d100 recv1 mode + (linuzappz) + + * 07/04/04:[+] FireWire IRQ is implemented ok now + [-] Forgot dev9Interrupt over R3000A.c + (linuzappz) + + * 05/04/04:[+] Added Firewire plugin protocol. (shadow) + + * 02/04/04:[-] VIF-FIFO transfers seems to work better ;) need testing + [+] Added GSreadFIFO + (linuzappz) + + * 30/03/04:[*] sstates now use CRC as well :) + [*] emuLog.txt now goes at 'logs' dir + (linuzappz) + + * 29/03/04:[*] GSdma now waits qwords transferred cycles + before clearing CHCR and triggering, + OPH and APATH are handled as well now. + (linuzappz) + + * 25/03/04:[*] Some rewritte over Sio.c + (linuzappz) + + * 24/03/04:[-] ostr size is now 1024 in Dis*.c + [!] Finally v0.7 :D + (linuzappz) + + v0.6: + * 21/03/04:[-] About dialog was cropping the testers, thx CK :) + (linuzappz) + + * 19/03/04:[+] Added a PadHack option at the cpu dialog + [-] Couple of fixes for release + (linuzappz) + + * 16/03/04:[-] CRC had a bug, now it's ok, sorry :) + [-] Fixed bug in memInit, thx gold :) + [-] LoadState now loads the tlbs + (linuzappz) + + * 16/03/04:[-] Fixed another silly bug in loadElfFile ;) + (linuzappz) + + * 15/03/04:[+] Added texts on the console Title to make patch makers life easier :P (shadow) + + * 15/03/04:[-] Fixed a free in loadElfFile + (linuzappz) + + * 14/03/04:[*] loadElfFile now reads the whole file first + [-] DMA4/7 interrupt timings are more accurate now + (linuzappz) + + * 12/03/04:[+] Added i386.asm, only used on linux so far, + compiles using nasm, it replaces the inline + assembling for Vif + [-] Fixed bug in UNPACK for skipping write + (linuzappz) + + * 11/03/04:[*] Patches names are now using crc, + instead of ie.: + Ridge Racer V PAL was SCES_500.00.pnach, + now it is 5BBC2F40.pnach + this way games with the same code + will not get confused + [-] Fixed bug in disR5900GetUpperSym + (linuzappz) + + * 10/03/04:[+] Added SQ/LQ over iVUmicro + (linuzappz) + + * 09/03/04:[-] sio2Reset was missing from psxHwReset + [-] Fixed sio pad swaps for 0x1100 mode + (linuzappz) + + * 08/03/04:[*] Modified the DEV9irq stuff + (linuzappz) + + * 05/03/04:[-] DEV9irq now issues a SBUS_IRQ + [*] malloc memory is now aligned to 16bytes + (linuzappz) + + * 02/03/04:[-] Added presaving for MMI ops that needed that + [-] vuJR/vuJALR now masks Fs with ~0x7 + (linuzappz) + + * 02/03/04:[+] stats.txt now dumps the Cpu mode + (linuzappz) + + * 01/03/04:[-] dmaGetAddr now uses memLUT + [+] Finally added USB plugins ;) + (linuzappz) + + * 26/02/04:[-] Fixed VUops that didn't have presaving + (linuzappz) + + * 22/02/04:[+] More ops at DisVUops.h + [-] VifDma.c is cleaner now, also fixed some + stuff for savestates + [-] Added some remaining vars at cpuBranchTest + to cpuRegs for savestates + (linuzappz) + + * 21/02/04:[-] Fixed ITOF0 + (linuzappz) + + * 20/02/04:[-] Fixed savestates ;) + (linuzappz) + + * 19/02/04:[*] VUflags now should handle overflow/userflow ok + (linuzappz) + + * 17/02/04:[*] Improved and fixed sio2 stuff + [-] Fixed _vuMFIR + (linuzappz) + + * 16/02/04:[-] DIV could crash when divisor == 0.0, + as well as ERSADD + (linuzappz) + + * 13/02/04:[-] Fixed FCAND over VU1ops.c + [*] Merged VU1ops/VU0ops/Vops to VUops + [*] Cleaned up VUflags.c + [-] hackedRecv now defaults to 0x1100 + (linuzappz) + + * 09/02/04:[-] VifDma.c MPG now clears the VU0/1 Mem though Cpu->ClearVU0/1 + (linuzappz) + + * 09/02/04:[-] More SCMD functions added. Still require working code for them. :) + (auMatt) + + * 06/02/04:[-] More iVUmicro.c opcodes, fixes, and stuff :) + (linuzappz) + + * 06/02/04:[-] Fixed Bios Detection for HK Bios. + (auMatt) + + * 06/02/04:[-] Fixed CdRom/CDVD Interrupt for 0x41000200 chcr, + now it interrupts after the read ends + (linuzappz) + + * 05/02/04:[+] Added FALSE/TRUE in GRecCommon.h + [+] Added more 16bit ops to x86.c/h + [+] Fixed SQD/SQI and implemented IOR/IAND over iVUmicro + [-] BIAS is now 2 again + [+] Now only MARK is writable at Hw.c, for vif0/1Regs + (linuzappz) + + * 03/02/04:[-] Fixed FALSE to GREC_FALSE in GRecMain.c + [-] Added break to F5 ;) + [-] Commented 'ERL Set' SysPrintf + (linuzappz) + + * 02/02/04:[-] Included stdarg.h in GRecCommon.h + [+] Added some scmds to CDVD.c (auMatt) + [+] cdvd.Status now changes to CDVD_STATUS_SEEK_COMPLETE, + after a CdRead CMD + (linuzappz) + + * 16/01/04:[+] Added LQI/LQD/SQI/SQD over Recompiler + [-] Updated EE BIAS to 8, need to test this + [!] SQI/SQD are diabled still, because they are still buggy + and i don't have more time... vacations :D:D + (linuzappz) + + * 15/01/04:[+] Added code for dma interrupts, for IPU FDEC, still commented + (linuzappz) + + * 14/01/04:[+] Temporary fix for PADS. F5 now change the pad mode on the fly. if your game doesn't work + switch it from there. (shadow) + + * 12/01/04:[*] FIFO is now really 128bit as it should be :) + (linuzappz) + + * 09/01/04:[-] Fixed VU->VI[0] != 0 bug in VU1, VU0, Macromode, JALR, BAL, LQI, LQD, SQI, SQD were setting VU->VI[0]. + Address in VCALLMS was incorrect, was causing crash in VF4. + (asadr) + + * 09/01/04:[*] Start to convert VIF stuff to functions instead of macros, right now I just converted + them duplicating the code for VIF0/1 and it is working but it is not the best yet, + commiting just so others can debug VIF while I finish the work, did some minor fixes + on VIF too. + [*] The only major function needed to be reduced to one is VIF0transfer/VIF1transfer, all + others are ok (I think). + (GoldFinger) + + * 09/01/04:[-] Fixed LQC2 for _Fs_ == 0 + [*] Fixed several SIF bugs (NoComp) + (linuzappz) + + * 06/01/04:[-] Fixed UNPACK modes in VIF.c, the Indeterminate fields are now set to 1 by default. (asadr) + + * 04/01/04:[-] Fixed a bug in LQD and LQI when _Ft_ was 0. + (GoldFinger) + + * 04/01/04:[*] Modified the VIFregister structure, both VIFs(0,1) have the exactly same + structure, just VIF0 does not use some of the registers, so I unified the + structures for easy reading and less bugs. + (GoldFinger) + + * 31/12/03:[-] Added USB API at PS2Edefs.h ;) + [+] More ops at DisVUops.h + [*] UNPACK now flushes the VU micro + (linuzappz) + + * 30/12/03:[-] Fixed savestates in Misc.c and added fixed VIFdma.h + (asadr) + + * 29/12/03:[-] Fixed bug for new vu code in savestates + (linuzappz) + + * 27/12/03:[-] Fixed bug in my last update for R5900.c + (linuzappz) + + * 26/12/03:[*] VUflags are now updated when Rd == 0 as well, changed only + at VU1ops.c + [*] VU1Regs/VU0Regs is now VURegs + [!] I think we should merge VU1ops/VU0ops/Vops + (linuzappz) + + * 24/12/03:[-] Fixed DMA8 for PsxDma.c + [*] LUI is now as it was before asadr's update + [*] readded 'if Log' over debugI at Interpreter.c + (linuzappz) + + * 18/12/03:[*] Restructured VU code and VIF. Fixed stuff in Interpreter + and added CTC2 VU1 Microinstruction caller. + (asadr) + + * 18/12/03:[*] Improvements to TLB code. + (linuzappz) + + * 17/12/03:[-] Fixed iCP0.h define to __ICP0__ + [+] Added disR5900GetUpperSym + (linuzappz) + + * 08/12/03:[+] SSE recompile of vus started. Some opcodes works some yet not. + Missing flags that i gonna add soon. Gives some speed boost :) + (shadow) + + * 05/12/03:[-] Fixed bug in GS for CSR stuff + (linuzappz) + + * 03/12/03:[+] Added Interlock for CFC2/CTC2 + [-] Fixed CFC2/CTC2/LQC2/SQC2, they now + check for zero registers + [!] This should fix the 'R0 is not zero' + and the 'VU memory overflow' hopefully ;) + (linuzappz) + + * 03/12/03:[+] You now disable vu0 macromode too when you disable vu recs by the + checkbox iR5900.c + [-] corrected some more bugg0rs of linuzappz sse instructions ix86_sse.c + [!] careful linuzappz's code. Don't ever trust him cause he is a lazy bugg0r + His mind is only for pampita!:) (shadow) + + * 02/12/03:[+] Added UNPCKLPSRtoR and MOVLHPSRtoR, there you go expert :) + (linuzappz) + + * 01/12/03:[-] Fixed savestates + (linuzappz) + + * 30/11/03:[+] a few sse instructions in sse.c + a much cleaner code in reccop2.c (shadow) + + * 28/11/03:[-] Recommited old VUops.h with asadr's EATANxy/EATANxz bugfixes + [!] asadr, the VUops.h you commited was in html format, + and some opcodes you change were only to slow down things, + commit other ones that need fixes. + (linuzappz) + + * 28/11/03:[-] Fixed alot of bugs in VUops.h, hopefully some stuff will now + work as it should (asadr) + + * 27/11/03:[*] fixed some stuff in recCOP2.c (shadow) + + * 25/11/03:[-] Fixed bug in Vif.c, masks hopefully are ok now ;) + (linuzappz) + + * 25/11/03:[-] Fixed Interpreter.c ix86.h include + [-] Added to GRecBasic.h a newline at end of file, linux + complains else ;P + (linuzappz) + + * 24/11/03:[+] Added cpu detection in interpeter.c too so now you can use SSE,MMX code in + interpreter too without the fear that your pc doesn't support it ;P (shadow) + + * 22/11/03:[+] By Nachbrenner request i added a memory patcher in Debugger.Now you can make patches + while pcsx2 is running. It is not yet finished as it can only patch 32bit data but + all the patches so far are 32bit so no problem ;P (shadow) + [!] Update Common.h . We are up to pcsx2 0.6 now! :) + + v0.5: + * 21/11/03:[-] Fixed Vif.c bugs :) + [!] Source code closed for release 0.5, + only bugfixes con be submitted + (linuzappz) + + * 21/11/03:[*] Started optimizing vif.c but I find so many strange stuff (problably bugs), please + linuz, check the comments I added on the vif.c file, and tell me what to do. + (GoldFinger) + + * 20/11/03:[*] Reorganize the cpu dialog a bit and added a new option. Disable vu recompiler + with disable the recompile of vu and will save some games from freeze when + vu memory overflows (quite often) :P . This will be removed when vu problems will + solve :P (shadow) + + * 19/11/03:[-] Fixed bug in savestates + (linuzappz) + + * 18/11/03:[*] Removed the old reg caching code including the sources, so now the only rec + that works is the normal one. + [*] GoldRec is progressing, I did lots of changes to make the progress better, + right now nothing works. + (GoldFinger) + + * 14/11/03:[*] Modified GSfreezeData, now it's plugin dependant + [+] Added SPU2freeze/DEV9freeze + [-] Fixed bug in inifile_read, hi shadow bugg0r :P + [-] Fixed bug in Sio2 + (linuzappz) + + * 14/11/03:[*] change pcsx2 patch system to use *.pnach files.Now you need a patches dir in your + pcsx2. (shadow) + [!] Am i the only one that write a changelog here?? (shadow) + + * 13/11/03:[-] fixed savestate naming in win32 and linux (shadow) + + * 06/11/03:[+] cleaned up a bit rec vu and enabled vu0 micro (shadow) + + * 06/11/03:[-] Workaround in VifDma.h for FiFo transfer ;) + (linuzappz) + + * 04/11/03:[*] Changed the way we handle SPR TTE transfers, also + MFIFO_VIFtransfer transfer always the ptag+2 + [-] Unhacked Sio.c for PADs ;) + [!] Now you gotta use the PADwinKeyb from PADwin at cvs + (linuzappz) + + * 03/11/03:[-] Fixed ba8R16 bug in Memory.c + [*] Enabled VU1 micro recompilation + [*] dmaGetAddr goes though memLUTR now + (linuzappz) + + * 02/11/03:[-] Fixed MSUBA had the same problem as MSUB, iFPU.c + A = A - B * C != A = B * C - A :) + (GoldFinger) + + * 01/11/03:[+] Addded cpu speed detection in cpu detection code + [!] Linuz fix the cpu_detection.c to work with linux pls ;p + [!] Goldfinger was right.Police 24/7 is okay with MSUB now :) (shadow) + + + * 01/11/03:[-] Fixed MSUB (MADD was ok), iFPU.c + Expert, please try in Police 24/7... :) + (GoldFinger) + + * 31/10/03:[-] Fixed PCPYLD, MMI.c + (linuzappz) + + * 30/10/03:[-] disable MADD,MSUB from iFPU. that ops was causing bugs in police 24/7. + Can't figure why, can someone? (shadow) + + * 29/10/03:[-] Commented D/T flags for VUmicro + (linuzappz) + + * 28/10/03:[-] Fixed memory rec issue, blah, shadow was right again :P + (linuzappz) + + * 27/10/03:[-] More fixes to memory stuff, hwregs for 128bit + [-] Fixed vifNum == 0 for UNPACKs + [-] DEV9_R_DEV now goes though DEV9read16 :) + [+] FiFo VIF1 can read data now ;) + [-] Fixed rec mem limit, shadow was right ;P + [!] Try Make Your Dream Home now ;) + (linuzappz) + + * 26/10/03:[-] Fixed Memory stuff, now it works ok :) + (linuzappz) + + * 25/10/03:[*] Some changes to memory cards. It's not what you all expect:P + (Florin) + + * 25/10/03:[*] Improved more the cpudetection routine at the Supporting Instruction sets features + [-] Improved a bit the MMI and fixed some bugs that prevent PII cpus to work (shadow) + + * 23/10/03:[-] Fixed a bug in Memory, untested actually ;), should fix + the loader rec bug + (linuzappz) + + * 24/10/03:[*] Improved the cpudetection routine in goldrec.Now more info appears :) + (shadow) + + * 23/10/03:[*] Improved VIF for transfers in parts + [-] Fixed some bugs in DisVUops.h ;) + [-] Fixed a bug in Memory, VU1.Mem was twice, thx shadow :D + (linuzappz) + + * 21/10/03:[-] Scratchpad memory was set bigger that it really is + [-] Uncommented a few tlb related printfs just in case ;) + (linuzappz) + + * 20/10/03:[*] Rewritten several Memory.c code, it's very untested, so far + i only tested bios, so tell me what's broken now :) + (linuzappz) + + * 18/10/03:[*] Fixed the rec for use with the tlb code, but this is a no go, slow as hell we must + change the whole tlb stuff, please linuz, lets think better before implementing this. + (GoldFinger) + + * 14/10/03:[*] Modified the memRead functions, now they're better for tlbs + misses, but note that they have one more arg, so gold, you'll + have to update the rec + (linuzappz) + + * 12/10/03:[*] Removed the new module in cvs called GoldRec. Now GoldRec is a directory under ix86-32. + (GoldFinger) + + * 10/10/03:[*] Removed the new recompiler from the main project and removed its dependencies, now there + is a new module in cvs called GoldRec, you must check it out. + (GoldFinger) + + * 10/10/03:[*] Improved TLB stuff a lot ;) + (linuzappz) + + * 07/10/03:[-] Fixed bug for recompiler in psx writes from Memory.c + (linuzappz) + + * 06/10/03:[*] VU0/1 now uses the VURegs struct + [+] Added the possibility to load the System.map from ps2linux + [+] Added TLB exceptions + [-] Fixed psxM accesses from Memory.c + (linuzappz) + + * 04/10/03:[*] rewrote the recompiled vu micro startup code and separate it + [-] remove the 3dnow code for reccop2 as it created more problems that it actually solved + [+] qmf2,qmtc2 is now done in SSE too . (shadow) + + * 01/10/03:[+] Handle for the EDI flag at ERET, a guess actually ;) + (linuzappz) + + * 30/09/03:[*] Reg caching works with bios and almost everything as normal rec does, need to + check better what does not work. + [*] Splitted iR5900.c into several .c files for easy navigation and for sanity + purposes as iR5900.c was HUGE. + [-] Fix LOTS of reg caching bugs, the main one was the comparission of 64bits registers. + (GoldFinger) + + * 30/09/03:[*] Added a base interrupt delay for the dma7 (spu2) + [*] More improvements to VifDma.h + (linuzappz) + + * 29/09/03:[-] Reimplemented Interrupt latency over R5900.c + [-] Fixed load/store unsigned addr to signed one over VUops.h + (linuzappz) + + * 28/09/03:[-] Fixed dmaIrq's for Source Chain mode + (linuzappz) + + * 26/09/03:[-] Fix the speed optimization problem that was in softCall function in Bios.c, + added a #pragma to disable optimization just to that function and everything + is working again as it should (linuz, please check if this pragma will interfere + with linux) + [*] The win32 project is back like before, the new Recompiler project was removed and + everything is working. + (GoldFinger) + + * 26/09/03:[+] Added two keys (F11, F12) for Opening/Closing the CDVD tray, + only for linux so far. + (linuzappz) + + * 25/09/03:[*] Sio2 fixes. Now the mcs are 'seen' as PS2 cards but unformated(able:P) + (Florin) + + * 25/09/03:[*] Modified the project structure under win32, I separated the recompiler from + the main project into a static lib, so now I can work with two projects instead + of one and enable optimizations. Now register caching works much better as I + enable speed optimizations in the Recompiler project but had to disable it in + the main project, the real problem is the global optimizations, this way I am + proving that the problem is not on my code... :) + [-] Fix lots of reg caching bugs and commented some of the reg caching instructions + that are buggy. Lots of demos work now, P51, colors, colors15 and maybe some others. + (GoldFinger) + + * 23/09/03:[-] Changed the MessageBox in recFunctions.c to SysMessage + [+] FIFO for VIF0/1 now works :) + (linuzappz) + + * 23/09/03:[*] Splitted the bios files so the code is the .c files and not on the .h files + [-] Fixed several bugs in reg caching and improved the routines + [!] Visual Studio .NET (dont know the others) speed optimizations are + messing with the code so it is recommended to build release mode + without Speed optimizations + (GoldFinger) + + * 23/09/03:[-] Commented the Syms in BiosInit.h, since they are only + for scph10000 + [-] Fixed ret DMA op + [+] Added iVUmicro, for recompiler + (linuzappz) + + * 22/09/03:[*] Added ExecuteVU0/VU1Block in R5900cpu, R5900.c + [+] Destination Chain for SPR0 dma and added Vif masking + [!] Gold, please merge the beta changes i sent you for + the iVUmicro.c/h + (linuzappz) + + * 20/09/03:[*] Now pad2 works in lle mode [tested with bios browser] + [+] New SCMDs and MC commands + [-] Fixes in sio, sio2, cdvd, etc. + [!] Now mcs appear as not inserted, but they are wip:P + SecrCardAuth() works fine;) + (Florin) + + * 19/09/03:[-] Small bugfix in Hw.h, u32 qwc -> u16 qwc; u16 pad; + [+] Small hack in Memory.c for ba000006 + (linuzappz) + + * 17/09/03:[-] Corrected a unpack bug i forgot ;) + [+] Implemented mskpath3 / m3r flags + [-] Fixed rom1.bin lookup for linux + (linuzappz) + + * 16/09/03:[-] Linuz fixed the macro bug hanging Visual Studio + (Gold-linuz) + + * 16/09/03:[-] More bugfixes/additions to Vif/VUs + (linuzappz) + + * 15/09/03:[-] Fixes lots of bugs in Reg Caching, now other demos work. + (GoldFinger) + + * 13/09/03:[-] Some fixes to the subq in cdvd.c (Florin) + + * 13/09/03:[-] Fixed the reg caching bug in tut1. + [*] Changed the DEFINE for reg caching for the config expert put on the CPU + screen, now we have both way to test. Thanks Expert. + (GoldFinger) + + * 13/09/03:[+] Added an option for enable regcaching or not.Now goldfinger should make + support for that!! (shadow) + + * 12/09/03:[-] Fixed the normal rec bug + [+] Added lots of new instructions for reg caching now all tutorials work + (demo 1 is strange), 3stars work also. + (GoldFinger) + + * 12/09/03:[-] Small bugfixes to Vif/VUs + (linuzappz) + + * 10/09/03:[*] More work on ipu (Florin) + + * 10/09/03:[-] New recompiler code wasn't compiling over linux, now it's ok + [-] Fixed VU memory64 writes masks + [+] Added Stats.c/h, it will create a stats.txt with some stats info, + if you define a NOSTATS in Common.h that will not be used + (linuzappz) + + * 09/09/03:[*] Improved the filter of ELF loading in GUI + [*] Register caching started to work, tutorial demo2a is working, others are coming. + [*] Commied ix86.c again with previous fix as linuz removed it. + (GoldFinger) + + * 09/09/03:[-] Fixed __int64 to u64 in Misc.c + [-] Fixed small bug in Vif.h + [-] Fixed bug in GS.c, bios is ok now + [+] Implemented INTC_STAT/MASK and DMAC_STAT for 64bits + [!] I commited the last ix86.c/h, afaik you only + reformatted it gold, please don't reformat my + code + (linuzappz) + + * 09/09/03:[-] Disabled host support for bios as it is buggy. + [*] Added/fixed SCMDs (2,3,1A) in cdvd.c (Florin) + + * 08/09/03:[+] Vif0/1 regs are now mapped to hardware + (linuzappz) + + * 08/09/03:[-] fixed bug in cpu ops debugger. Now all opcodes should appear .(For you goldfinger!) + (shadow) + + * 07/09/03:[+] Completed phase 1/2 of adding host support for bios. (Florin) + + * 06/09/03:[-] Fixed bug in rec when using ezmpeg + * 06/09/03:[*] Re-structuring the whole recompiler to make it easier for + debug and for the sake of understanding + (GoldFinger) + + * 06/09/03:[*] Many things fixed/changed in ipu files (Florin) + + * 05/09/03:[+] Hot keys for savestates in win32 + F1 -> savestate + F2 -> change the slot + F3 -> loadstate + [+] checkbox for enable the patches in cpu dialog + (shadow) + + * 05/09/03:[+] Some more VUmicro debugging + (linuzappz) + + * 05/09/03:[+] Added VDEC & BDEC; now m2v files work but ipu files do not + (Florin) + + * 05/09/03:[-] bug fixed in ifpu.h (shadow) + + * 04/09/03:[+] Added Init of Plugins before Loading of + savestates. + [-] LoadOthers in WinMain.c had a plugin init + missing fixed that. + [!] Fixed GSsoft aswell. And increased vRam size from 4*1024*1024 + to 2*4*1024*1024 as OpenGL doesn't handle wrapping around in + memory. + (asadr) + + * 04/09/03:[+] HSync stuff, and better CSR/IMR handling + [+] Few more FPU insts in ix86.c/h + [!] Please tell me if something is now screwed :) + (linuzappz) + + * 04/09/03:[-] ipu fixes to dmas and vdec (Florin) + + * 02/09/03:[-] fixed the patch system + (goldfinger) + + * 02/09/03:[*] working savestates in win32 :) + (shadow) + + * 01/09/03:[*] Working savestates for linux :) + (linuzappz) + + * 02/09/03:[-] Bug fixes in IPU.c (still hacky when returning BP) + Now ezmpeg gets to VDEC;) (Florin) + + * 01/09/03:[-] Fixed old bug in Sio.c/CdRom.c + (linuzappz) + + * 30/08/03:[+] sceCdReadSubQ <- that is a bad name; it look more like + a gettoc entry (SCMD2) (Florin) + + * 29/08/03:[+] Started the register caching implementation, not ready to test yet + some new x86 opcodes to x86.c and .h iR5900.c is completely changed + a new define for iR5900.c is used to enable reg caching. + (GoldFinger) + + * 29/08/03:[-] Removed 3DNOW code is the FPU since 3DNOW is 64bits, + and FPU is 32bits + [+] Workaround in ElfHeader.c for pukklink, so it will + load ok with Run Cd + [+] Savestates :D + [-] Maybe fixed patches, blah :P + (linuzappz) + + * 27/08/03:[+] CdGetToc + CdReadSubQ + [*] Changed PS2Edefs specs 0.4.3 / CDVD v3 + [*] Changed back the CDVDgetTD function to have a 2nd param: cdvdTD + (Florin) + + * 26/08/03:[-] Fixed patching bug in BiosInit.h that was used only for scph10000 + (Florin) + + * 26/08/03:[*] SPR address in DMAs are now masked with 0x0fffffff + (linuzappz) + + * 25/08/03:[-] Fixed patch stuff + (shadow-linuzappz) + + * 25/08/03:[-] Fixed IDEC bitstream decoding. Now, all *.ipu files + should work fine (Florin) + + * 25/08/03:[-] Fixed VIF Transfers to include MARK reg in VIF0 aswell. + (asadr) + + * 22/08/03:[*] Changed the SSE opcodes to Macro mode (thanks Linuz) and linuz added some more + (GoldFinger) + + * 22/08/03:[-] Changed DEV9 stuff to use DEV9 plugins + (linuzappz) + + * 21/08/03:[+] Added SSE instructions ADDPSRtoR, ADDPSMtoR, SUBPSRtoR, SUBPSMtoR, MULPSRtoR, + MULPSMtoR, MINPSRtoR, MINPSMtoR, MAXPSRtoR, MAXPSMtoR, SQRTPSRtoR, SQRTPSMtoR, + RSQRTPSRtoR, RSQRTPSMtoR, RCPPSRtoR, RCPPSMtoR, CVTPS2PIRtoR, CVTPS2PIMtoR, + CVTPIPS2RtoR, CVTPIPS2MtoR, CMPEQPSRtoR, CMPEQPSMtoR, CMPLTPSRtoR, + CMPLTPSMtoR, CMPLEPSRtoR, CMPLEPSMtoR to ix86.c ( need to compile and check ) :P + (GoldFinger) + + * 21/08/03:[+] Added Patch.c + (shadow-linuzappz) + + * 19/08/03:[+] Fixed bug in PsxHw.h, thanks to psycho_tr + (linuzappz) + + * 15/08/03:[+] More to SMAP + (linuzappz) + + * 14/08/03:[-] Fixed Debugger/RDebugger + [!] There is still one bug left i saw in the RDebugger, + that's the threads are not ended ok, but i'll leave + that to you florin :) + (linuzappz) + + * 12/08/03:[*] Changed the time in CDVD.c and some WIN32 defines to __WIN32__ + (Florin) + + * 08/08/03:[+] Started SMAP/DEV9 stuff + (linuzappz) + + * 06/08/03:[-] Fixed MFIFO for GS dma + (linuzappz) + + v0.41: + * 05/08/03:[-] Uncommented some sif WIP stuff :) + [*] Addeded 0x00100008 PC for cpuExecuteBios as well + [-] Fixed silly bug in CDVD.c for DvdReads + (linuzappz) + + v0.4: + * 29/07/03:[-] Fixed bug in Sif code ;) + (linuzappz) + + * 26/07/03:[-] Fixed the dma memory checking for the scratchpad, + and implemented it over the remaining dmas + (linuzappz) + + * 25/07/03:[-] GSdma now ends when a transfer is outside the memory + [-] Bugfix to Sif1 dma + [-] Some changes in the ICFG write code, and + when D5_CHCR == 0, psxSu32(0x30) = 0x40000; + (linuzappz) + + * 22/07/03:[-] Counters fixes/improvements + [*] Improvements on CdRead/DvdRead + [*] Better Sif1/0 handling + (linuzappz) + + * 22/07/03:[+] New PS2Edefs 0.4.0 :) + (linuzappz) + + * 20/07/03:[-] DvdRead was really 2064 :P + (linuzappz) + + * 19/07/03:[-] Fixed BIG stupid bug in FiFo.c that i left there:P + [!] I'm ashamed:( + [*] Fixed getBits function with back buffer;) + [!] I'm proud of that B-) (Florin) + + * 18/07/03:[-] Fixed includes for Mpeg.c/yuv2rgb.c + [-] Modified DvdRead, uses 2048 blocksize, experimental ;) + [-] CDVDgetTD had to return s32, not u32 + [*] Some reorganization for the rec + (linuzappz) + + * 18/07/03:[-] Fixed some memory allocation bug in IPU.c + [i think there are more, searching...:P] (Florin) + + * 17/07/03:[-] Fixed another Sio bug ;) + [-] Fixed MULT1/MULTU1, s64 was really s32 + [-] Commented out the interrupt delay thingy ;), was causing + troubles with Kengo 2 + [+] Implemented DvdRead + (linuzappz) + + * 17/07/03:[-] Fixed bug in FiFo.c that caused flickering between movies + [*] Fixed color conversion (Florin) + + * 16/07/03:[-] Now we can boot games though bios :) + [-] Fixed 32bits shifts in Interpreter.c + (linuzappz) + + * 16/07/03:[*] Fixed (somehow:P) IDEC so that .ipu files works a bit (Florin) + + * 15/07/03:[*] Changed cdvdLoc stuff to lsn + [-] PsxDma10 now will just return if bcr < 4 + [-] Corrections to IPU1/0 dma transfers, untested but should be fine ;) + [!] Breaks compat with current cdvd plugs + (linuzappz) + + * 15/07/03:[+] CSC + PACK ipu commands Fixes to bitstream decoding (Florin) + + * 14/07/03:[-] Really implemented MFIFO now ;P + [!] mfifo.elf works just fine now, also tekkentag reaches a bit further + (linuzappz) + + * 14/07/03:[+] Some more work on IntraDECoding for IPU (florin) + + * 14/07/03:[-] Some cleaning over Sif.c + [+] MFIFO implemented in both GS/VIF + [-] Fixes to xpadman + (linuzappz) + + * 13/07/03:[*] VUmicro code now can run in "async mode" + [-] Fixed TTE in SPR1 dma + (linuzappz) + + * 10/07/03:[-] Fixed bug in R5900.c when HLE mode was on + [-] fileio ain't crashing anymore when the file is not there + [-] Fixed interrupts on VifDma.h + (linuzappz) + + * 09/07/03:[-] Fixed bug in GS dma transfers when TTE is enabled. + Was passing wrong size of qword now it is GSgifTransfer3(ptag+2, 4) + + * 08/07/03:[*] In Win32 cdvdReadRTC gets correct time. (Florin) + + * 08/07/03:[-] Fixed stupid bug in SPR1 dma, thanks florin :) + (linuzappz) + + * 07/07/03:[-] Fixed bug in Vif UNPACK cmd, tops was *16 ;) + [*] GSgifTransfer/2 => GSgifTransfer1/2/3 (PATH1/2/3) + [*] Updated GS.c with VifDma.h asadr changes, commented the TTE + transfer by now + [*] Updated as well the SPR1 dma + [!] Note that now all vu1 demos work :D + (linuzappz) + + * 06/07/03:[+] Implemented cdvdReadKey + (linuzappz) + + * 05/07/03:[+] VCALLMS/VCALLMSR now are implemented + [*] SPU dma4 now has a delay base of 0x10000 + [-] VifDma.h is now mostly as before asadr rewrote it + last time, since that way had problems with the TTE chcr + flag, now go check the bios Browser ;) + (linuzappz) + + * 04/07/03:[-] IOP won't die now after cpuRegs.cycle overflows :), R5900.c + (linuzappz) + + * 03/07/03:[-] Fixed WriteRTC and bug in Sio.c + (linuzappz) + + * 03/07/03:[+] Some IPU commands (BCLR,FDEC,SETIQ,SETVQ,SETTH) & IPU fifo + (Florin) + + * 02/07/03:[-] Cleaned a bit VifDma.h + [*] Modified the DmaExec macros, now the Dmas take care + to interrupt and to clear the STR bit + (linuzappz) + + * 30/06/03:[*] Usb hack ;), PsxHw.c + (linuzappz) + + * 29/06/03:[*] Modified Iop DMAs for async processing, only for spu/spu2 by now + [-] Vif dma refe/end now sets the tadr to 0, tek4 loops else, but + now is crashing after ;) + [!] sven shows one screen now, and others want to ;) + (linuzappz) + + * 29/06/03:[-] Removed the experimental code i added yesterday from CDVD.c/h + [*] Improved EE/IOP Rcnts + (linuzappz) + + * 28/06/03:[*] More on iop rcnts rewrite + [+] Experimental code in CdRead, now if the lsn sector is + the same than the last one readed it will add nSectors + to it, ie. it readed 2 sectors from 0:2:16; and then + it issues another cdread with the same lsn, it will read + from 0:2:18. + (linuzappz) + + * 27/06/03:[*] Started iop rcnts rewrite, untested and more to come ;) (linuzappz) + + * 27/06/03:[-] Some fixes on iop rcnts + [+] Implemented the SPU2async func + (linuzappz) + + * 26/06/03:[-] Really fixed HLE mode ;). (linuzappz) + + * 26/06/03:[-] Small CDVD.c corrections. (linuzappz) + + * 24/06/03:[*] Fixed elf loader at least not to crash at bad elfs. (Florin) + + * 23/06/03:[*] Added "rom1.bin" as a valid file for rom1 filesystem. (Florin) + + * 23/06/03:[-] Small fix to CDVD.c, maybe fixed a time out problem + with some cdvdman versions. + (linuzappz) + + * 20/06/03:[+] Some mcds work, PsxSio2.c, Sio.c + (linuzappz) + + * 17/06/03:[+] SPU dmas now call the correct funcs, PsxDma.c + (linuzappz) + + * 17/06/03:[-] Fixed Sio2, PADs are working :D, Sio.c, PsxSio2.c + [-] Fixed language in CDVD.c, now's english again :) + (linuzappz) + + * 16/06/03:[-] Better error handling over CDVD.c + [+] ROM1 stuff, Memory.c/h, PsxMem.c, iR3000A.c, iR5900.c + [!] PCSX2 now detects the rom1 in this way: ie. + you use scph10000.bin, then you must have + in the same dir scph10000.bin.rom1 or scph10000.rom1 + (linuzappz) + + * 16/06/03:[-] Rewrote the VIFtransfer and VIFdma again. Better speed and + compatibility this time (asadr). + + * 16/06/03:[*] Reoverwritten CDVD.c/h with my CDVD.c/h, + this is simpler, more direct and faster, + CdRom.c, PsxHw.c, R3000A.c, PsxCounters.c, + Memory.c + [-] Kinda workaround i think in the ICFG reg + (1450), PsxHw.c + [-] Removed VSyncHack at least ;), WinMain.c, + Common.h, ini.c + [!] Games start showing something :D:D + (linuzappz) + + * 15/06/03:[+] More dummy cdvd scmd (Florin) + + * 14/06/03:[-] Fixed SIF0 transfers, PsxDma.c, PsxHw.c/h. + [*] Cleaned up SIF1, R3000A.c, Sif.c + [+] Added a Run CD menuitem, WinMain.c, resource.h + [!] Bios shows something :D:D + (linuzappz) + + * 12/06/03:[-] Fixed bug in release version (unsafe compiler optimizations:P) + (Florin) + + * 11/06/03:[+] More functions on lle cdrom (cdread) (Florin) + + * 10/06/03:[+] Rudely overwritten linuzappz work in CDVD.c/.h + [!] Sorry man, i think i did the best...i created a framework + with names and so on. Also we have to talk about;) (Florin) + + * 10/06/03:[+] Started CDVD.c/h, moved old CDVD.h to CDVDlib.h, + PsxMem.c, PsxCommon.h (linuzappz) + + * 10/06/03:[*] Added new SPU2 dma functions plugin.c + [*] New PS2 plugins specifications 0.3.2 (shadow) + + * 09/06/03:[+] Add SPU2read/SPU2write to PsxMem.c + [-] Few fixes to PsxCounters.c + [+] Added PsxDma7, PsxHw.c, PsxDma.c (linuzappz) + + * 09/06/03:[-] Sif0 chaining fix (Florin) + + * 08/06/03:[+] Started with SIO2... (Florin) + + * 07/06/03:[-] Fixes to SIF0/SIF1 :D + [!] Now OSDSYS loads ok, and so does several modules in iop, + bios now gets stuck in a Deci2Call (reqsend) + (linuzappz) + + * 07/06/03:[-] Fixes0, Fixes1 (Florin;) + + * 06/06/03:[*] Fixed and improved the VIF Dma transfers and rewrote the VIF_Transfer. It's far + more compatible and fast ( all vu1 demos work:D ). (asadr) + + * 06/06/03:[*] Fixed sif1 (...waiting for a better solution;) (Florin) + + * 05/06/03:[-] Sif1 flags fixes (still buggy?) (Florin) + + * 04/06/03:[*] Some adjustments to PsxInterpreter.c (Florin) + + * 03/06/03:[-] Set the PSXCLK to 36.864 Mhz, by now, later PSXCLK should be + a variable, Common.h + [*] Improved iop hw maps, added DMA9/10, PsxDma.c/h, R3000A.c, PsxMem.c + [+] Added RCNT3/4/5 in PsxCounters.c/h, PsxBios.c, PsxHw.c/h + [+] Added a bit more of loggin in PsxInterpreter.c + [-] 0xba000006 now returns 1, for some bioses, Memory.c + [*] Improved dmaSIF1, SIF.c, and cleaned dmaSPR1, SPR.c + [!] Finally my name is on the v0.4 :P + (linuzappz) + + * 03/06/03:[-] Fixed GetPS2ElfName in Misc.c (Florin) + + * 22/05/03:[+] new flags code based in nsx2 flag code. vuflags.c vuflags.h + [*] vuops.h rewrote almost all the vu opcodes with new flags code Upper Instructions + should be okay but might still are some issues with the Lower instructions. + [-] added proper reset in vu1micro.c + [*] added the new vcnet files for compile properly with vuflags + (shadow) + + * 21/05/03:[-] Fully fixed of recSQ in iR5900.c. + [-] Fixed EMMS_TRACING on none 3DNOW machines, EMMS_TRACING now turned on again. + [*] Added CPU autodetection to iR5900.c + [!] #define CPU_3DNOW is not used now. + (Alexey Silinov) + + * 20/05/03:[-] Dummy fix of recSQ in iR5900.c. Recompiler back to work again. + (Alexey Silinov) + + * 10/05/03:[*] Improved fpu.c, just code optimizing in cvt_s, cvt_w, all branches opcodes and + some code organizing. + (GoldFinger) + + * 02/05/03:[+] Added some ioprps to Misc.c (Florin) + + * 02/05/03:[+] Some more work on Padman module 800100Xpadman.c , 800100Xpadman.h (shadow) + + * 30/04/03:[+] Added 2 more syscalls in BiosSysc.h (Florin) + + * 29/04/03:[+] More threads functions. (see threads.txt) + [!] To see threads switching, comment the 3 instructions + at the top of _ThreadHandler function (Bios.c) + (Florin) + + v0.3: + * 01/05/03:[-] Fixed dvd iso issue (roundup of numsectors ...+2047/2048) + in CDVDiso.c (Florin) + + * 30/04/03:[-] Fixed bug in CFC1, Fpu.c + [-] Fixed branches isns on VUops.h, US was instead of SS + [-] Added newline at oef for MMI.c, *mtapman.c + [-] Included in *loadfile.c + [*] Few changes over languages, Misc.c/h, WinMain.c + (linuzappz) + + * 29/04/03:[-] Added a workaround for the interrupt latency in the rec, + R5900.c + (linuzappz) + + * 28/04/03:[-] Fixed a bug in BiosInit.h, instead of 16 dmas there was 15 + [-] Counters 0,1,2 had interruption disabled, Counters.c + (linuzappz) + + * 27/04/03 [-] WinMain.c now only calls GetPS2Elf if on HLE mode + [-] parseCommandLine had a bug when not using HLE, ElfHeader.c + [*] Implemented memRead/Write128, Memory.c/h, iR5900.c + [*] Implemented a better way to count opcodes in iR5900.c + [*] Rewrote AddIntc/DmacHandler, RemoveIntc/DmacHandler, Bios* + (linuzappz) + + * 24/04/03:[*] More threads functions. (see threads.txt) (Florin) + + + * 23/04/03 [-] Undo the "VU0/1 control/integer regs are now the same" update, + VU*, DebugReg.c, (goldfinger-linuzappz) + [+] Implemented latency interrupt thingy ;), R5900.c/h + (linuzappz) + + * 21/04/03 [-] DMAC interrupt wasn't setting the cause in a0, Bios.c + [+] DMACTable is now being used with DefaultDmacHandler, Bios.c/h, + BiosInit.h, HLE.c + [+] Added dummy handles for mtapman901/3, Rpc_services.h, *mtapman* + [*] VIF0 code is now shared with VIF1 code, Vif.c, VifDma.h + (linuzappz) + + * 23/04/03:[*] Fixed RFU061_InitHeap, EndOfHeap, CreateThread, InitThreads + (Florin) + + * 21/04/03:[+] Started threads update (Bios.c/BiosInit.h/BiosSync.h/ + deci2_dbgp.c/ElfHeader.c/.h) (Florin) + [-] Fixed fifos a bit:) (FiFo.c/Hw.h) (Florin) + [*] Fixed VIF1 regs display in Hw.c. I know that those were handeled + but now is more clear (Asad-Florin) + + * 20/04/03:[-] Fixed a bug in WinMain.c. In case of the debuggers with HLE bios, + cpuExecuteBios() was not called, so the tlbs and all stuff + were not inited properly. (Florin) + + * 20/04/03:[-] Fixed a bug in VUmicro.h + [+] VIF1dma now handles 'from Memory' transfers, Vif.c + [-] F11 now un/sets Log, F12 un/sets symbol logging, WinMain.c + (linuzappz) + + * 19/04/03:[-] Fixed a bug in Interpreter.c + [-] VU0/1 control/integer regs are now the same, VU*, DebugReg.c + [*] Cleaned a bit GS.c + (linuzappz) + + * 17/04/03:[-] gsRead32 wasn't calling GSread32, lol :), GS.c + [+] Implemented more syscalls, as dummy for now, Bios.c/h, BiosSysc.h, + HLE.c + [*] Removed the CSR revision/intelace bits over GS.c + [+] Added GSirqCallback to PS2Edefs.h, GS.c, Plugins.c + [+] VIF1 cmd now handles the i bit, still not 100% correct, Vif.c + [-] Fixed several VIF1 bugs, Vif.c + (linuzappz) + + * 16/04/03:[*] biosInit is now called at hle_bootstrap, Bios.c, HLE.c, WinMain.c + [+] Added _TlbInit at biosInit, Bios.c + [*] Deci2Call is now better coded, Bios.c, BiosSysc.h + [-] Fixed some bugs over AddIntcHandler/AddDmacHandler, BiosSysc.h + [+] bios_SetSYSCALL is now implemented, BiosSysc.h + (linuzappz) + + * 17/04/03:[+] Breakpoint support for debugging bios. (Florin) + + * 16/04/03:[-] Readded an update that linuzappz missed in his src, + that was then used by many pcsx2 team members. [it is about my 16/03/2003's] + [+] sceCdReadIOPm in 80000595.c + (Florin) + + * 14/04/03:[*] Memory access bug in deci2 that made pcsx2 to crash. hi linuzappz + [+] MC functions fixes/dummies over 80000400mcserv.c + (Florin) + + * 12/04/03:[*] CP0Count now adds 2 every opcode, instead of 4 + (linuzappz) + + * 12/04/03:[-] Bios VSyncSetFlag is now fixed ok, Bios.c + [*] Started to implement new Bios code, Bios.c/h, BiosInit.h + BiosSysc.h, EEregs.h, HLE.c, R5900.c/h + [!] Please tell me if this update creates some incompatibility, + or something else works now, since the INTC/Exceptions code is + much better now :). + (linuzappz) + + * 08/04/03:[-] DMAC_STAT CIS? bits are now set after a DmaExec, Hw.c + [-] Fixed bug when a plugin returned -1, WinMain.c + [*] Cleaned a bit GSdma, GS.c + [-] Fixed bug in INTC interrupts, Bios.c + (linuzappz) + + * 07/04/03:[+] Added cpu opcodes debugger. Use the CPU ops button in the debugger + and it will create a cpuops.txt with the opcodes that used. + Debugger.c pcsx2.rc, cpuopdebug.c cpuopdebug.h . Now works only in + interpreter. (shadow) + + * 04/04/03:[+] Added LabelGreets/LabelAuthors to Misc.c/h, AboutDlg.c + [*] Languages code over pcsx2 is a bit better, WinMain.c + [+] Added Log to STDOUT over Logging dialog, pcsx2.rc, + Misc.c, resource.h + [+] Now we're emulating the VSync Start and the VSync End, Counters.c + (linuzappz) + + * 26/03/03:[*] Optimized PLZCW in mmi.c (GoldFinger) + [-] fixed MADD1 and MADDU1 in mmi.c (GoldFinger) + [-] PSLLH, PSRLH and PSRAH (sa needed to be the first 4 bits only), + mmi.c (GoldFinger) + [-] PADDSW, the manual seems to be wrong (well it is) so I tryed + to fix it, mmi.c (GoldFinger) + [-] PADDSB, PSUBSB, the comparision was wrong, mmi.c (GoldFinger) + [-] PADDSW, PSUBSW, PADDSH, PSUBSH, PADDSB, PSUBSB, PADDUW, PSUBUW, PADDUH, + PSUBUH, PADDUB, PSUBUB, the sum and sub need a conversion to the higher + value(s16,s32 and s64), mmi.c (GoldFinger) + [-] PMINH, the comparision needs to be signed, mmi.c (GoldFinger) + [-] PHMSBH, was wrong, fixed, mmi.c (GoldFinger) + [-] PEXEH, PREVH, was using _Rs_ when only _Rt_ should be, mmi.c (GoldFinger) + + * 26/03/03:[*] fixed fpu bugs. Hi linuzappz :) . Tmip is correct in interpreter mode finally + fpu.c (shadow) + + * 24/03/03:[+] Fixed Trap instructions, hi shadow :), also cleaned + up a bit the Interpreter.c (linuzappz) + + * 22/03/03:[+] Fixed the 'Load ELF File' issue, added the Memory Dump menu, + WinMain.c (Florin-linuzappz) + [!] I forgot the changelog entry in the last update, + please read it (linuzappz) + [!] I've updated again the pcsx2.po, florin sent one without the + linux port messages since i've never updated u the linux port ;) + + * 20/03/03:[+] Added GSsetWindowInfo, WinMain.c, PS2Edefs.h, Plugins.c + [+] Added MiltuLingual support, using gettext, WinMain.c, Plugins.c, + AboutDlg.c, ConfigDlg.c, pcsx2.rc, Memory.c, iR5900.c, iR3000A.c, + pcsx2.dsp, Sio.c, R5900.c, PsxMem.c, Hw.c, Common.h, ini.c, + resource.h, Win32.h + [-] Fixed IPU.c when IPU_LOG is not defined + [-] Fixed padman/loadfile.c when RPC_LOG is not defined + [*] Removed dummy memory area, Memory.c/h, PsxMem.c/h + (linuzappz) + + * 17/03/03:[*] add some more stuff to DisR5900asm.c . win debugger is better now (shadow) + [-] fix a bug in rec table (visubiu not exist) in macromode .. recCop2.c (shadow) + [!] recheck vu micromode tables. Hmm they seem correct (shadow) + + * 16/03/03:[+] Added "next" (aka "step over") support for deci2 debugging + [+] Added TTYP support (log redirection) (buggy;have to test more) + (Florin) + + * 15/03/03:[*] move loadfile to rpc using florins protocol hi florin;p (shadow) + + * 15/03/03:[*] Fixes to breakpoints in deci2 stuff (Florin) + + * 13/03/03:[+] More deci2 dbgp stuff (BREAK/CONTINUE/RUN) + [!] It is not fully tested. This is EXPERIMENTAL code. + [!] It may contain many bugs and there are also "known issues". + [*] changed names of shadow's padman files and made the according + changes to rpc_services.h & bios.c (Florin) + + * 12/03/03:[*] rewrote padman+xpadman according to florins protocol on RPC folder + [*] removed code from bios.c according to pad handling.. + [+] Add fix that make analog mode to work partially ;) (try turnip) (shadow) + + * 10/03/03:[+] Added more mem mappings to PsxMem.c & Memory.c in order + not to crash the emu when read from a not-covered area (Florin) + + * 10/03/03:[-] fix small bug in winmain that didn't let console to close winmain.c (shadow) + + * 04/03/03:[+] Added remaining UNPAKs and cleaned a bit, Vif.c/h (linuzappz) + + * 03/03/03:[*] replace console writes of IPU with IPU_LOG Ipu.c (Shadow) + + * 01/03/03:[-] Fixed partially FIFO bug; (unlogged change:P) + [!] I haven't fixed it all because is very messed up. + [+] Added a small fix to PsxMem.c in order to allow sifman to stay resident. + (Florin) + + * 28/02/03:[+] Added support for remote debugging with tcp/ip deci2 protocol. + [!] Not finished nor fully tested + [!] There's an issue on Win98 with winsock2 closing [have 2 check that] + [!] New src dir (rdebug\*.*), Win32\RDebugger.c/.h; + [!] also added ws2_32.lib to link libraries + (Florin) + + * 25/02/03:[+] Added 8bit DMAs to Hw.c + [+] More UNPACK cases to Vif.c (linuzappz) + + * 23/02/03:[+] Added BC0s in COP0.c + [!] the BC0s are still fake, but they should be ok ;) (linuzappz) + + * 22/02/03:[*] Now if the Recompiler fails to initialize it'll switch to interpreter (linuzappz) + + v0.2: + * 18/02/03:[-] Small fix in winmain.c in SysInit() causing a crash (shadow) + + * 12/02/03:[+] Added new DMA transfer codes to VIF.c, GS.c + [+] Added the new clipping code to the VU + [*] Fixed most of the VU ops. Better compatibility + [!] The new dma transfer code is 4-5% faster than the last one. :) + + * 12/02/03:[*] Fixed iR5900.c to include iR5900.h, moved some stuff from + ix86.h to iR5900.h + [-] Fixed CPU_LOG flags over iR5900.c/recCOP2.c + [+] Added some SysPrintfs over iR5900.c after x86Init + (linuzappz) + + * 26/01/03:[+] Added some defines in Hw.h (linuzappz) + + * 26/01/03:[-] Fixed include in IPU.c, 'common.h' for 'Common.h', + SJdata.c, 'rpc/...' '...' (linuzappz) + + * 04/02/03:[+] ix86.c: Added CPUID for linux. + SSE is autodetected now (linuzappz) + + * 28/01/03:[+] ix86.c: CPUID added. It will work if u don't change CPU on the FLY. :) + [*] ir5900.c: recompiler changed for CPUID. + [*] recCOP2.c: recompiler changed for CPUID. + (Alexey Silinov) + + * 27/01/03:[+] ir5900.c: recompile of DSRAV,PMINW,PMAXW added. + [!] I'am not sure in this code.Need find demos that use it. + [+] ix86.c: PANDNRtoR,PANDMRtoR added. + (Alexey Silinov) + + * 25/01/03:[-] ir5900.c: Some fpu opcodes for non 3DNOW version fixed with EMMS_TRACE on. + After Linuzappz request:memory opcodes + [-] (LB,LBU,LH,LHU,LW,LWU,.....,SB,SH,SW,...) fixed for version with EMMS_TRACE on. + [-] recCOP2.c: Bugfixed for non 3DNOW version(added another recCOP2SPECIAL1t,recCOP2SPECIAL2t tables). + + [!] Now EMMS_TRACE will work much better. + (Alexey Silinov) + + * 24/01/03:[+] ir5900.c: DSRA,DSRA32 recompilation added. + [*] shifts by _Imm_=0,_Rs_=0 optimized. + [+] PMFHI,PMFLO,PAND,PXOR,PMTHI,PMTLO,POR,PAND now can recompiled to SSE instructions. + [-] JUMPS bugfixed by putting SET_FPUSTATE before it, + because cpuBranchTest use FPU. Pillgen now ok with EMMS_TRACE. + [!] #define CPU_SSE in ix86.h if you have Pentium3/4 or Duron7/AthlonXP. + (Alexey Silinov) + + * 24/01/03: Fixed iR5900.c to compile without 3DNOW (linuzappz) + + * 24/01/03: Moved the emms's in Hw.c, GS.c, Memory.c to iR5900.c (linuzappz) + + * 24/01/03: Rewrote ini.c, same code as Pcsx now :) (linuzappz) + + * 24/01/03: Removed the browse info option over pcsx2.dsp (linuzappz) + + * 24/01/03: Some fixes in Hw.c, missings #ifdef HW_LOG/#endif, + reordered the ipu address and the IPU1 dma was wrong. (linuzappz) + + * 21/01/03: remove the fpu flags reorganize fpu.c a bit. Send code for using it + as reference to all the pcsx2 members. + + * 21/01/03:recCOP2.c + 75% of COP2 ops recompiled used 3DNOW. + only sign MAC flags updated. + Zero,Sticky will be done later. + (Alexey Silinov) + * 19/01/03: + ir5900.c: + Fixed recompiling of RSQRT_S for3DNOW,recPCPYUD(tskin.elf now ok), + recC_LE for x87 FPU(untitled.elf last part now ok). + Optimizing recompile of recADDI,recADDIU,recDADDI,recDADDIU, + recANDI,recORI,recXORI,... (check _Rs_,_Rt_= =0,!=0). + Optimiing recMOVZ,recMOVN only one JMP CC,.. needed. + Added #define EMMS_TRACE to. + Added #define ARITHMETICIMM_RECOMPILE,ARITHMETIC_RECOMPILE,etc. + (Alexey Silinov) + * 18/01/03: ir5900.c:Many recompiler opcodes fixed. + IPU DMA logging update. + (Alexey Silinov) + + * 18/01/03: Fixed fileio_lseek function in 80000001fileio.c. (Florin) + + * 16/01/03: Rewrite fpu and added two version of it. One with flags and + one without. The no flags version is much faster. + fpu.c ,r5900.h,common.h,r5900.c,ini, resources , winmain.c (shadow) + + * 15/01/03: Added memory mapping of IPU_CMD,IPU_CTRL,IPU_TOP,IPU_BP. + Added parsing of IPU commands. + (Alexey Silinov) + * 14/01/03: recMAX_S,recMIN_S,recC_F,recC_EQ,recC_LE,recC_LT-added. + recABS_S,recNEG_S-now don't use FPU. + ix86.c - 3DNOW opcodes added. + #ifdef CPU_3DNOW then FPU recompiled using 3DNOW instruction set. + Now we are ready TODO FPU register cache on CPU_3DNOW. + gs.c add emms before GS read,write. + (Alexey Silinov) + + * 14/01/03: Fixed stupid bug in 80000001fileio.c (Florin) + + * 13/01/03: Fixed some issues in CDVDiso.c & 80000597cdvdfsv.c (Florin) + + * 11/01/03: Fixed fileio [important] functions up to ioprp255 (Florin) + + * 11/01/03 some more MMI opcodes in rec (alexey silinov) + + * 10/01/03 recPADDUB-changed,recPADDUH-added (Alexey Silinov) + + + * 09/01/03 + My copy&paste bugs in recPCPYUD,recPAND,recPXOR fixed. + Now EMMS() instruction writing only before FPU commands if FPU state is MMX.With it size of recompiled code is reduced. + !!Added macros SET_FPUSTATE,SET_MMXSTATE it's must before MMX or FPU instruction. + Fixed many ops.ExtSign32to64() don't used anymore. it's faster and smaller to do CDQ(). + recLUI,recPCPYLD optimized. + Added recompilation of PMAXH,PMINH,PCGTB,PCGTH,PCGTW,PCEQB,PCEQH,PCEQW,PEXTLW,PEXTUW. + ir5900.c,ix86.c, ix86.h + (Alexey Silinov) + + + * 07/01/03: Fixed MADD, MADDA, MSUB, MSUBA opcodes in FPU.c ( asadr ) + + * 07/01/03: added MTSAB,MTSAH in interpreter.c (asadr) + + * 07/01/03: Added Flags in FPU.c, fixed SQRT, DIV, RSQRT opcodes in FPU.c ( asadr ) + + * 07/01/03: add some opcodes in interpreter.c (shadow) + + * 07/01/03: small fix in mult1,multu1 in MMI.c (shadow) + + * 07/01/03: more addes in recompiler iR5900.c (Alexey Silinov) + + * 07/01/03: fixed MULT,MULTU,MULT1,MULTU1 in rec and added DIV1,DIVU1 iR5900.c + (Alexey Silinov) + + * 07/01/03: add several MMI opcodes to recompiler iR5900.c ix86.c ix86.h + (Alexey Silinov) + + * 07/01/03: Fixed libpad version issues; added scePadInit2 support in Bios.c (Florin) + + * 06/01/03: Added sceDvdRead function to 80000595cdvdfsv.c, CDVDiso.h/.c + Moved sifcall_cdvdfsvA from Bios.c to 80000592cdvdfsv.c (Florin) + + * 05/01/03: Fixed libmc version 80000400mcserv.c + Added support for cdrom device in LoadHeap function 80000003sysmem.c (Florin) + + * 05/01/03: Added D and I Flag checking in vuDiv and SQRT opcodes and some more fixes ( asadr ) + + * 05/01/03: Merge all the vu code fixes to the better possible one vuops.h (shadow) + + * 05/01/03: Several vu fixes vuops.h (Alexey Silinov) + + * 04/01/03: Added temporary fix to vuDIV, vuRSQRT, vuERSADD, vuERCPR, ERSQRT ( asadr ) + + * 04/01/03: Added vuERCPRL, vuESUM , vuEATANxz, vuESIN, vuEATAN, vuEEXP, vuRXOR ( asadr ) + + * 04/01/03: Fixed GetPS2ElfName Misc.c + Romanian version pcsx2ro.rc & spell fixes in pcsx2.rc (Florin) + + * 03/01/03: Added callback support in Bios.c + Added function name display support (if you know other places, plz add...) + (Florin) + + * 02/01/03: Fixed sceCdRead (cdvdfsv1.4 and more?) 80000595cdvdfsv.c (Florin) + sceCdSeek, sceCdPause, sceCdStop, sceCdStatus + + * 02/01/03: Added SLTI,SLTIU,SLT,SLTU iR5900.c ( Alexey Silinov) + + * 02/01/03: Added SETS8R ix86.c ix86.h ( Alexey Silinov) + + * 01/01/03: YAH HAPPY NEW YEAR :) + + * 30/12/02: Added Dump memory button in Debug dialog over Debugger.c (Florin) + + * 29/12/02: Start work on Savestates Common.h, Misc.c. Need to include zlib.lib in project (shadow) + + * 29/12/02: Fix small bug In ERET. COP0.c (shadow) + + * 29/12/02: Some more Vu opcodes in the vuops.h (shadow) + + * 29/12/02: Added BC2F,BC2T,BC2TL,BC2FL not sure if i check the right bit althought Vu0.c (shadow) + + * 29/12/02: Added HLE opcode over DisR5900.c (linuzappz) + + * 29/12/02: Fixed some bugs on rec mode, Memory.c, PsxMem.c, + ix86.c/h, iR3000A.c, iR5900.c (linuzappz) + + * 29/12/02: Fixed JALR in Interpreter.c (linuzappz) + + * 28/12/02: Fixed stupid old bug in iR5900.c (linuzappz) + + * 26/12/02: Added compiler detection code (Win32/WinMain.c) (Florin) + + * 20/12/02: Refixed new Threads code, a bit hacky still ;), Bios.c/h, HLE.c (linuzappz) + + * 20/12/02: Refixed Counters.c, GS.c (linuzappz) + + * 20/12/02: Changed some cop0 names over DisR5900.c (linuzappz) + + * 20/12/02: Fixed EXL bit on cpuException, R5900.c (linuzappz) + + * 20/12/02: Fixed ERET, COP0.c, Interpreter.c, R5900.h (linuzappz) + + * 19/12/02: fix bugs in fileio system 80000001fileio.c (florin) + + * 19/12/02: rewrite MMI mmi.c (linuzappz) + + v0.1: + * 17/12/02: Small cleaning for release (linuzappz) + + * 17/12/02: Fixed a comment in CDVD.h (linuzappz) + + v0.046: + * 17/12/02: FIXED THAT BASTARD BUG with interpreter + R5900.c (shadow) + + * 16/12/02: Fixed CDVDFS_read function (CDVDisodrv.c). (Florin) + + * 07/12/02: Added support for SjDATA filesystem (SJdata.c/.h). + Small fixes in 80000003sysmem code. + Moved OpenPlugins call from debugger.c to WinMain.c + Added support for 0B001337cdvd rpc driver. (Florin) + + * 06/12/02: Fixed RPCVER for games that load ioprp.img. + Moved related code Bios.c to Misc.c. (Florin) + + * 05/12/02: Placed a guard in CDVDFS_init/CDVDisodrv.c + Added support for reading from cdvd in Elfheader.c/.h + Implemented RunCD option WinMain.c, GtkGui.c, Misc.c/.h (Florin) + + * 01/12/02: Made fileio_open more compatible with games (up to 2.0F/ioprp255) (Florin) + + * 30/11/02: Add test opcodes TGE,TGEU,TLT,TLTU,TEQ,TNE Intepreter.c (shadow) + + * 30/11/02: Add exceptions defines in R5900.h (shadow) + + * 01/12/02: Removed old VU0 code over VU0.c (linuzappz) + + * 31/11/02: Implemented CheckCdrom/LoadCdrom, still unfinished, Misc.c (linuzappz) + + v0.045: + * 31/11/02: Changed memRead32 for PSMu32 over Interpreter.c (linuzappz) + + * 31/11/02: Fixed CdRead, CDVDiso.c (linuzappz) + +// * 30/11/02: Added irqs for rcnt2/3, started thread HLE code rewrite, +// Bios.c, Counters.c (linuzappz) + + * 28/11/02: Fixed win32 fileio path, and some more small issues (linuzappz) + + * 27/11/02: Added BD0000X0 connection to 1000F0X0 and BC000000 ee memmap, + implemented direct rec clears, and added some more counters stuff, PsxMem.c/h, + Memory.c/h, iR3000A.c, iR5900.c, Counters.c/h, Hw.c, PsxHw.c (linuzappz) + + v0.044: + * 26/11/02: Added RPC handler for 80000595cdvdfsv + Fixes in iso handling system (read function can read more than 16KB) + Fixed issue with deci2call no.3 (junk re-printing) (Florin) + * 20/11/02: Automatic setting of RPCVER + (problems: 1. SDK samples do not load an ioprp; default is "2000";) + 2. starwars game load a ioprp.img; so RPCVER="0000") + Fixed bug in CDVDiso.c/CdRead(); check for null pointer + Fixed issue with the Joliet filesystem (Florin) + * 09/11/02: Added iso parsing & filesystem driver from libcdvd library by Hiryu & Sjeep + Added credits (Hiryu&Sjeep) to Aboutbox & Readme.txt + Changed the order of opening of plugins in Plugins.c/OpenPlugins() + Added (or moved code from bios.c) to handle RPC user & standard code + -works (or should work; needs intensive testing): + 014D704Enaplink, 80000001fileio, + 80000003sysmem, 80000592cdvdfsv, + 80000597cdvdfsv + -dummy (to be implemented; only params display): + 0B0110C5sjpcm, 0badca11amigamod(shadow), + 80000400mcserv,80000596cdvdfsv, + 80000601osdsnd + Added RPC_LOG logging stuff to debug.h, pcsx2.rc & resource.h + Added kputs handling for scePrintf in Deci2Call syscall in bios.c + (Florin) + + v0.043: + * 06/11/02: add some work for amigamod.irx HLE based on Florin + RPC code (shadow) + + * 21/10/02: implement some more opcodes for VU + flags in many opcodes + (shadow) + + * 19/10/02: Added more opcodes to VUops.h (from VU0.c), and started the implementation of flags, + VUflags.h, VU* (shadow-linuzappz) + * 12/10/02: Added fix for several bioses, Hw.c, removed hack for 30002R.bin R5900.c (linuzappz) + + * 06/10/02: Added 0xb2000000 map area as a 0x12000000 mirror, Memory.c (linuzappz) + + * 06/10/02: Added/Fixed some VIF1 unpack cases, Vif.c (linuzappz) + + * 06/10/02: Started Rewrite of SetGsCrt, Bios.c (linuzappz) + + * 05/10/02: Improved gsReads/Writes GS.c (linuzappz) + + * 28/09/02: Added iop HLE code for exceptions in PsxBios.c (linuzappz) + + * 24/09/02: Added ps2 bios check for config dialog in ConfigDlg.c/GtkGui.c (Florin) + + * 23/09/02: Added command line parsing for main's argc, argv in ElfHeader.c (Florin) + + * 14/09/02: Fixed small issue in PsxBios2.c/h, Bios.c (linuzappz) + + * 13/09/02: Fixed bug in Bios.c for sif_call (linuzappz) + + v0.042: + * 25/08/02: Fixed VU SQRT/RSQRT, also added ERSQRT, VUops.h (linuzappz) + + * 24/08/02: Added several stuff for IOP hle (linuzappz) + + * 09/08/02: Added: PADDSW, PSUBSW, PPACW, PADDSH, PSUBSH, PEXTLH, PPACH, PADDSB, PSUBSB, + PPACB, PEXT5, PPAC5, PABSW, PCEQW, PMINW, PADSBH, PABSH, PCEQH, PMINH, + PCEQB, PSUBUW, PADDUH, PSUBUH, PSUBUB, PEXTUB, QFSRV, PSLLVW, PSRLVW, + PINTH, PROT3W, PSRAVW, PEXCW, PEXCH, PINTEH, PMTHI, PMTLO, PEXEW, + PREVH, PEXEH, in MMI.c (GoldFinger) + + * 09/08/02: Changed: PADDUB to conform to defines (GoldFinger) + + v0.041: + * 11/08/02: More to VUops.h (shadow) + + * 10/08/02: Rewrote L/R Stores/Loads (linuzappz) + + * 05/08/02: Add some more opcodes to VUops.h some demos works again(shadow) + + * 04/08/02: Added VUops.h, VU0.c/h, still uncomplete (linuzappz) + + * 04/08/02: Added GSgifTransfer2 for PATH1, VU1micro.c, PS2Edefs.h, Plugins.c (linuzappz) + + * 03/08/02: Added unpack v4-32, Vif.c (linuzappz) + + * 02/08/02: Rewrote partially VUmicrocode, structures and stuff, VU1/0micro.c, VUmicro.h (linuzappz) + + * 02/08/02: Small change on Misc.c (linuzappz) + + * 01/08/02: cpuExecuteBios is now called before the LoadElf, WinMain.c (linuzappz) + + * 01/08/02: Added a couple of HW_LOGS in Hw.c (linuzappz) + + * 01/08/02: Fixed MFC2/CFC2 in DisR3000A.c (linuzappz) + + * 01/08/02: Added small hack on R3000A.c (linuzappz) + + * 01/08/02: Fixed bug in StartThread Bios.c (linuzappz) + + v0.040: + * 31/07/02: Small change in PsxInterpreter.c and PsxHw.c (linuzappz) + + * 31/07/02: Added CDVDgetTN and CDVDgetTD, PS2Edefs.h, Plugins.c, CdRom.c/h (linuzappz) + + * 30/07/02: Fixed Gte.c, now includes PsxCommon.h (linuzappz) + + * 30/07/02: Added GPU_LOG to Debug.h (linuzappz) + + * 30/07/02: IOP now has vsyncs, PsxCounters.c/h (linuzappz) + + * 30/07/02: Added PsxGPU.c/h, moved the GPU_xx stuff from PsxBios.c, PsxDma.c (linuzappz) + + * 24/07/02: Added psxSIF1transfer to R3000A.c,, Sif.c, still not working (linuzappz) + + * 24/07/02: Added a couple of address more to PsxHw.c (linuzappz) + + * 24/07/02: Added zeroEx func to trace writes to stdout, PsxInterpreter.c (linuzappz) + + * 24/07/02: Improved bios_write, PsxBios.c (linuzappz) + + * 24/07/02: PsxMem.c now handles the full 4mb of the bios mem (linuzappz) + + * 24/07/02: Hack for 30002R bios, R5900.c (linuzappz) + + * 24/07/02: Fixed BNEL, BEQL in disR5900.c (linuzappz) + + * 22/07/02: Remove biosCall, now use only biosException, Bios.c/h, Interpreter.c, + R5900.c (linuzappz) + + * 21/07/02: Intialaze of VU1 vu1microc,vumicro.h,R5900.c (shadow) + + * 21/07/02: implement VIF0transfer same way as VIF1transfer vif.c (shadow) + + * 20/07/02: Add debug logs in vu0,vu1 micromode + vu0 execute vu0micro.c, + vu1micro.c,vumicro.h (shadow) + + * 18/07/02: Clean up vu0 macromode vu0.c (shadow) + + * 19/07/02: PsxMem.c now handles 0xbf80xxxx hw addresses (linuzappz) + + * 17/07/02: IOP PRid is 0x1f (not 0x2), R3000A.c (linuzappz) + + * 17/07/02: More to VU1micro.c (shadow) + + * 14/07/02: Added psxMemRLUT/psxMemWLUT instead of only psxMemLUT, PsxMem.c/h (linuzappz) + + * 11/07/02: Added MADD1, MADDU1, PMFHL, PCGTW, PMAXW, PADDH, PSUBH, PCGTH, + PMAXH, PADDB, PCGTB, MMI.c (goldfinger) + + v0.039: + * 08/07/02: Commented the 0xe000 hw dma test, for jasper, Hw.c (linuzappz) + + * 08/07/02: Changed PADreadStatus for PADstartPoll/PADpoll, Plugins.c, PS2Edefs.h, Bios.c, + PsxBios.c, Sio.c (linuzappz) + + * 07/07/02: More to Vif1 dma and added vu1ExecMicro, Vif.c, VU1micro.c/h (linuzappz) + + * 06/07/02: Rewritten/updated iop code, CdRom.c/h, Common.h, Iop*, Psx*, Debug.h, + Decode_XA.c/h, DisR3000A.c, ElfHeader.c, Gte.c/h, Mdec.c/h, R3000A.c, + R5900.c/h, Sio.c/h, iR3000A.c, Bios.c, pcsx2.dsp (linuzappz) + + * 05/07/02: Added CDVDreadTrack/getBuffer and now we're using CDVD plugin, PS2Edefs.h, + Plugins.c, ConfigDlg.c, ini.c pcsx2.rc (linuzappz) + + * 05/07/02: Optimized recANDI and completed the mmi rec tables, iR5900.c,ix86.c/h (linuzappz) + + * 06/07/02: Add VU opcodes tables vu1micro.c,vu0micro.c,vumicro.h (shadow) + + * 03/07/02: Added MADDU, PMTHL, PLZCW, PSLLH, PSRLH, PSRAH, PSLLW, PSRLW, PSRAW in MMI.c(goldfinger) + + * 03/07/02: Small change in MULT1, MULTU1 for speed, MMI.c(goldfinger) + + * 03/07/02: Fixed MADD, PLZCW in MMI.c(goldfinger) + + * 03/07/02: Fixed signed extend in DIVU, SLL, SLLV, Interpreter.c(goldfinger) + + * 03/07/02: Fixed C_F, FPU.c(goldfinger) + + * 04/07/02: Fixed silly bug on Bios.c, also added a workaround on Counters.c (linuzappz) + + * 04/07/02: Refixed CVT_W/S, FPU.c (linuzappz) + + * 03/07/02: Fixed DIV/DIVU and implemented MOVZ/MOVN in iR5900.c (linuzappz) + + v0.038: + * 02/07/02: Small change on CVT_W, FPU.c (linuzappz) + + * 01/07/02: Changed a bit IPU.c/h, added the dmaIPUs on Hw.c and added IPU_LOG, Debug.h, + resource.h, pcsx2.rc, Common.h (linuzappz) + + * 30/06/02: Add the remaining vif regs in the structure vif.h (shadow) + + * 30/06/02: Framework for IPU ipu.c,ipu.h (shadow) + + v0.037: + * 30/06/02: Added a couple of MMI opcodes to iR5900.c, ix86.c/h, also added one more cdvd server, + Bios.c (linuzappz) + + * 29/06/02: Added most of the FPU opcodes on the recompiler, fixed DSRLV/DSLLV, and also added + LQ, SQ, MFHI, MFLO, MTLO, MTHI, iR5900.c, ix86.c/h (linuzappz) + + * 28/06/02: Refixed LDL,LDR,SDL,SDR, Interpreter.c (linuzappz) + + * 27/06/02: Fixed bug in ABS, FPU.c and completed more fpu opcodes on DisR5900.c + fix to vu0 (vu0.c) + (shadow-linuzappz) + + * 27/06/02: Fixed fileio for dummy files, Bios.c (linuzappz) + + * 26/06/02: Changes/(fixes?) to some opcodes in interpreter.c SRA,DSRA,MULT,MULTU + ,SDL,SDR,LDR,LDL.At least cubemastah is correct now!(GoldFinger) + + * 20/06/02: Fixed the new Logging, modified the files on the last entry + WinMain.c (linuzappz) + + * 18/06/02: Realtime Logging Debugger.c,resource.h,pcsx2.rc,ini.c, + Common.h,debug.h (you must enable it!)(need to fixed) (shadow) + + * 18/06/02: Add some work for sjpcm module on Bios.c (shadow) + + v0.36: + * 13/06/02: Fix basic3d on Bios.c (linuzappz) + + * 09/06/02: Fix for call/ret dma in GS.c (shadow) + + * 06/06/02: Started CDVD plugin API on PS2Edefs.h (linuzappz) + + * 06/06/02: Started HLE.c/h, Interpreter.c, Common.h, iR5900.c, InterTables.c/h (linuzappz) + + * 04/06/02: Added some more syscalls on Bios.c (linuzappz) + + * 02/06/02: Fixed some bugs on SPR.c, Sif.c, Vif.c (linuzappz) + + * 02/06/02: More work on DisR5900asm.c (shadow) + + * 02/06/02: More stuff on Vif.c/h and SPR.c (linuzappz) + + * 01/06/02: Started SIFdmas Hw.c, Sif.c/h, Common.h, added SIF_LOG to Debug.h, + also removed the BREAK code since the bios doesn't handles that, Interpreter.c (linuzappz) + + * 01/06/02: Added PLZCW to MMI.c (linuzappz) + + * 01/06/02: RFU060 is now as before, added INTC and DMAC stuff, added INTC regs 0x1000f000 and + 0x1000f010, and DMAC 0x1000e010, Hw.c/h, Bios.c, Counters.c, R5900.c/h (linuzappz) + + * 31/05/02: Thread stuff is better now, added RFU061 and fixed RFU060, Bios.c (linuzappz) + + * 30/05/02: VU0 stuff is almost complete on DisR5900asm.c (shadow) + + * 30/05/02: Set gp on ElfHeader.c (linuzappz) + + * 30/05/02: Renamed _LOG to EMU_LOG, Debug.h, WinMain.c (linuzappz) + + * 28/05/02: Implemented GetCop0/iGetCop0 bios calls, Bios.c (linuzappz) + + * 28/05/02: Added names to GPR/COP0 regs, R5900.h, COP0.c, Bios.c, Interpreter.c, + FPU.c, DisR5900.c, R5900.c, VU0.c, MMI.c, iR5900.c, ElfHeader.c (linuzappz) + + * 28/05/02: Fixed PSUBW, PSUBB, added PADDW, PEXTLB, PEXTUH, MMI.c, PERF + on Interpreter.c, and TLBWR, TLBR to COP0.c (linuzappz) + + * 28/05/02: disasm.c/h is now DisR5900asm.c, Debugger.c, Debug.h, also added symbols + support for it (linuzappz) + + v0.35: + * 27/05/02: INCREASE VERSION ON 0.036! WinMain.c (shadow) + + * 27/05/02: add partialy support for VU0 in Win32 disasm.fix a bug in tables for MMI + disasm.c disasm.h (shadow) + + * 27/05/02: add VU1 register debugger. resource.h, pcsx2.rc,debugger.h, debugreg.c (shadow) + + * 27/05/02: Started real threads stuff on Bios.c (linuzappz) + + * 27/05/02: Rewrote dmaGIF/dmaVIF1, GS.c/h, Vif.c/h, Hw.c/h (linuzappz) + + * 27/05/02: add Macros for VU0Mem + Some new VU0 opcodes VISWR,VILWR, (shadow - [TyRaNiD] ) + + * 27/05/02: add some new Defines (_Id_ _Is_ _It_ _Imm5_) and some new opcodes + VIADD,VISUB,VIOR,VIAND,VIADDDI,VFOI12,VFOI15,VABS (shadow) + + * 26/05/02: Added support for Symbols on DisR5900.c, ElfHeader.c, Debug.h, + also refixed the qwc on SPR.c (linuzappz) + + * 26/05/02: Added some cdvdfsv stuff on Bios.c, also set the gs revision to 3 in + CSR, GS.c (linuzappz) + + * 25/05/02: CTC2/CFC2 to DisR5900.c (linuzappz) + + * 25/05/02: Added BREAK opcode on Interpreter.c (linuzappz) + + * 25/05/02: Now the b0000000 to b2000000 address are handled as a 10000000 mirror, + Hw.c, Memory.c (linuzappz) + + * 25/05/02: Removed some old code on R5900.c, rewrote a bit the ElfHeader.c (linuzappz) + + * 24/05/02: Add gsWrite... on bios_SetGsCrt (tyranid) + + * 24/05/02: MULT1/MULTU1 are now ok MMI.c (linuzappz) + + * 24/05/02: Added 1000f000 addr on hwRead32, Hw.c (linuzappz) + + * 23/05/02: add VU0 opcodes VSUBi,VSUBq,VMULA,VMULAi,VMULAq,VMSUB,VMSUBi, + VMSUBq,VMADDA,VMAX,VMINI,VADDA,VADDAi,VADDAq,VADDAx,VADDAy, + VADDAz,VADDAw,VSUBA,VSUBAi,VSUBAq,VSUBAx,VSUBAy,VSUBAz,VSUBAw, + VMSUBA,VMSUBAx,VMSUBAy,VMSUVAz,VMSUBAw,VMSUBAi,VMSUBAq (shadow) + + * 23/05/02: add VU0-1 status. (vu0.h , vumicro.h) (shadow) + + * 23/05/02: Added VU0/1micro.c/VUmicro.h (shadow) + + * 23/05/02: Fixed bios_isceSifDmaStat (return -1), also started some work on the + zero-exception stuff, Bios.c, IopBios.c, R5900.c (linuzappz) + + * 23/05/02: VRNEXT should be fine now, VU0.c (linuzappz) + + * 23/05/02: Small addition on Bios.c, 0x80000003 cmd on bios_isceSifSetDma (linuzappz) + + * 22/05/02: Added define __VU0_H__ on VU0.h (linuzappz) + + * 22/05/02: Rewritten GSdma/dmaGIF stuff, now only GSgifTransfer exists, added dmaGIF to GS.c, also added + GIF_LOG to Debug.h, Plugins.c/h (linuzappz) + + * 21/05/02: Fixed one bug in WinMain.c, now can rerun a elf ok (linuzappz) + + * 21/05/02: More stuff to Vif.c (linuzappz) + + * 20/05/02: Fixed one bug in biosException (linuzappz) + + * Started SPRdmas, SPR.c/h, Hw.c, Common.h, also added SPR_LOG, Debug.h (linuzappz) + + * 'call' dmaChain mode in dmaVIF1 should be right now (linuzappz) + + * More changes to the GS plugin API, GSdmaGIF/GSdma, PS2Edefs.h, Plugins.c, Hw.c, Vif.c, + also fixed little bug in SPU2init (linuzappz) + + * Small change in GSmakeSnapshot, now pass char *path (linuzappz) + + v0.34: + + * add more opcodes to Disasm DisR5900.c (shadow) + + * correct MTSA in interpreter interpreter.c (_Rs_ and not _Rd_) (shadow) + + * fixed FPU register debugger debugreg.c .Now registers appears float (shadow) + + * Some more stuff on Bios.c/Counters.c, timer1 intc, fixed bug in CreateSema (semaid stuff), + and added iSignalSema (linuzappz) + + * Added some VU0 opcodes to DisR5900.c (linuzappz) + + * Fixed bug in FPU.c, BC1XX branch delay (linuzappz) + + * Started Vif0/1 dmas, Hw.c, Vif.c/h, Common.h, added VIF_LOG to Debug.h (linuzappz) + + * Fixed VSUBx, VMULz, renamed VMONE to VMOVE, VU0.c (linuzappz) + + * Moved COP2 from Interpreter.c to VU0.c, and MMI to MMI.c (linuzappz) + + * fixed VU0 register debugger debugreg.c (Linuzappz-shadow) + + * Added ExecuteBlock and removed ExecuteBios on R5900cpu, R59000.h, Interpreter.c + and iR5900.c, also added psxExecuteBios, R5900.c, WndMain.c (linuzappz) + + * Some fixes to VU0.c, _Rd_ == 0, not _Rd_ != 0 (linuzappz) + + * Added MTHI1/MTLO1, MMI.c (linuzappz) + + * Rewrote Memory.c (linuzappz) + + * Improved iR5900.c branchs, and updated ix86.c/h (linuzappz) + + * Fixed bug in MULTU, (u64) stuff (linuzappz) + + * Interrupt Exception code was wrong, 0 -> 0x400 (linuzappz) + + * Started ChangeLog + diff --git a/Docs/License.txt b/Docs/License.txt new file mode 100644 index 0000000000..7d1f8605f8 --- /dev/null +++ b/Docs/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/Docs/PS2Edefs.txt b/Docs/PS2Edefs.txt new file mode 100644 index 0000000000..5442da8297 --- /dev/null +++ b/Docs/PS2Edefs.txt @@ -0,0 +1,443 @@ + PS2E Definitions v0.3.0 (beta) + ------------------------------ + + Author: linuzappz@pcsx.net + +Note: Refer to PS2Edefs.h for more info. + +1) API Funcs +2) FAQs +3) Notes + +1) API Funcs: + --------- + + Common stuff: + ------------ + +// u32 CALLBACK PS2EgetLibType(void); + +Gets the plugin type, from the following defines: + +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +Note that the types can be ORed so you can make an +ie. GS/PAD plugin in one dll. + +// u32 CALLBACK PS2EgetLibVersion(void); + +Will get the plugin version: + +const unsigned char version = 1; // GS library v1 +const unsigned char revision = VERSION; +const unsigned char build = BUILD; // increase that with each version + +return version<<16|revision<<8|build; + +'version' is the GS plugin API version, as this is beta, +it should be 1. +'revision' and 'build' are plugin defined values. + +// char* CALLBACK PS2EgetLibName(void); + +Get the LibName, ie. "GSsoftdx Driver"; + + + + GS plugin API: + ------------- + +Basic funcs +----------- + +// s32 CALLBACK GSinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK GSopen(void *pDsp, char *Title); + +Opens the plugin, return 0 on success, else -1. +The plugin must fill the 'pDsp' arg (32bit) that'll be +passed to other plugins (*1), this is OS dependant (*2). + +On Win32: pass a HWND value, ie: + *(long*)pDsp = (long)GShwnd; +On Linux: pass a Display value, ie: + *(long*)pDsp = (long)display; + +*1 Even if this value is passed to every plugin, this +may not be used by the plugins. + +*2 This could change anyways, ie. maybe you can code a +GS/PAD plugin for a speacial library, so the pDsp +will be a value that you need to communicate between +them (if you need to do this). + +// void CALLBACK GSclose(); + +Close the plugin. + +// void CALLBACK GSshutdown(); + +Shutdown the plugin. + +// void CALLBACK GSvsync(); + +Called on every VSync. + +// void CALLBACK GSgifTransfer(u32 *pMem, u32 size); + +Transfer 'size' qwords (128bit) from 'pMem' to the Gif. + +// void CALLBACK GSgifTransfer2(u32 *pMem); + +Transfer a qwords (128bit) block from 'pMem' to the Gif. + +// void CALLBACK GSwrite32(u32 mem, u32 value); + +Writes to address 'mem' data 'value', 32bit. +Addresses can range from 0x12000000 to 0x14000000. + +// void CALLBACK GSwrite64(u32 mem, u64 value); + +Writes to address 'mem' data 'value', 64bit. +Addresses can range from 0x12000000 to 0x14000000. + +// u32 CALLBACK GSread32(u32 mem); + +Returns 32bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +// u64 CALLBACK GSread64(u32 mem); + +Returns 64bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +Extended funcs +-------------- + +// void CALLBACK GSkeyEvent(keyEvent *ev); + +Gets called when there is a keyEvent from the PAD plugin + +// void CALLBACK GSmakeSnapshot(char *path); + +Makes an snapshot of the vRam, can be a with the full +vRam or just the view area (as you prefer), to the dir +'path'. + + +// #ifdef __WIN32__ +// s32 CALLBACK GSsetWindowInfo(winInfo *info); +// #endif + +Windows only function, will pass the info struct to the +GS plugin, if the plugin will use this info it should +return 1 (TRUE), else the emu will destroy the window +handle and let the plugin take care of that. +This function must be called before the GSopen. +Note that the emu should hide the hMenu and the hStatusWnd +if it they are set. +The position and size of the window is not specified and +should be reset by the plugin, but the window passed should +be in a normal state, not maximized nor minimized. +After a GSclose the emu must destroy the window and +recreate it. + +// void CALLBACK GSconfigure(); + +Configure the plugin. + +// void CALLBACK GSabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK GStest(); + +Returns 0 if the plugin should work ok, else -1. + + + + PAD plugin API: -=[ OBSOLETE ]=- + -------------- + +Basic funcs +----------- + +// s32 CALLBACK PADinit(u32 flags); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK PADopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK PADclose(); + +Close the plugin. + +// void CALLBACK PADshutdown(); + +Shutdown the plugin. + +// keyEvent* CALLBACK PADkeyEvent(); + +Called every vsync, return NULL if no event happened. + +// u8 CALLBACK PADstartPoll(int pad); + +Starts polling data from the PAD, 'pad' can be 1 (pad1) +or 2 (pad2). +Returns first byte from buffer; + +// u8 CALLBACK PADpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt" or "padmem.txt", +for info about value/buffer data. + +// u32 CALLBACK PADquery(); + +returns: 1 if supported pad1 + 2 if supported pad2 + 3 if both are supported + +Extended funcs +-------------- + +// void CALLBACK PADconfigure(); + +Configure the plugin. + +// void CALLBACK PADabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK PADtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SIO plugin API: + -------------- + +Basic funcs +----------- + +// s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); + +Inits the plugin, return 0 on success, else -1. +port/slot combination will be used to load the corresponding + configuration data from ini. It's like an id for the instance. +'f' is a callback function that is used by SIO_TYPE_MTAP capable + plugins to change active slot in emulator (since sio is emu-controled). + +// s32 CALLBACK SIOopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK SIOclose(); + +Close the plugin. + +// void CALLBACK SIOshutdown(); + +Shutdown the plugin. + +// u8 CALLBACK SIOstartPoll(u8 value); + +Starts polling data from the SIO, 'value' is + 0x01, 0x21, 0x61 and 0x81 corresponding to pad, mtap, rm and mc. +Returns first byte from buffer; + +// u8 CALLBACK SIOpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt", "padmem.txt" or + "padspecs.txt" (http://ps2dev.ps2-scene.org/padspecs.txt), +for info about value/buffer data. + +// u32 CALLBACK SIOquery(); + +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +returns: ORed value of SIO_TYPE_xxxx - the capabilities of the plugin +eg. a remote control plugin will return SIO_TYPE_PAD | SIO_TYPE_RM + +Extended funcs +-------------- + +// void CALLBACK SIOconfigure(); + +Configure the plugin. + +// void CALLBACK SIOabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK SIOtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SPU2 plugin API: + --------------- + +TODO :) + +Basic funcs +----------- + +// s32 CALLBACK SPU2init(); +// s32 CALLBACK SPU2open(void *pDsp); +// void CALLBACK SPU2close(); +// void CALLBACK SPU2shutdown(); +// void CALLBACK SPU2update(); +// void CALLBACK SPU2dma(u32 *dmaAddr, char *pRam); +// void CALLBACK SPU2write(u32 mem, u16 value); +// u16 CALLBACK SPU2read(u32 mem); + +Extended funcs +-------------- + +// void CALLBACK SPU2configure(); +// void CALLBACK SPU2about(); +// s32 CALLBACK SPU2test(); + + + + CDVD plugin API: + --------------- + +Basic funcs +----------- + +// s32 CALLBACK CDVDinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK CDVDopen(); + +Opens the plugin, return 0 on success, else -1. + +// void CALLBACK CDVDclose(); + +Close the plugin. + +// void CALLBACK CDVDshutdown(); + +Shutdown the plugin. + +// s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +Starts reading from the specified 'lsn' sector location, +return 0 on success, else -1. + +// u8* CALLBACK CDVDgetBuffer(); + +Gets a pointer to the buffer with the sector data +readed by a previously CDVDreadTrack call. +The buffer size depends on the mode used for readTrack. + +note: return can be NULL (for async modes) + +// s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq); + +Read subq data from disc at 'lsn' location (only cds have subq data), +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); + +Get the the cdvdTN data for the currect CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTD(u8 Track, cdvdLoc *Buffer); + +Get the the cdvdTD data for the 'Track' track in the current CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTOC(void* toc); + +Get ps2 style toc from disc, return 0 on success, else -1. +(ps2 toc isnt quite the same as a normal disc toc, +especially for dvds) + +// s32 CALLBACK CDVDgetDiskType(); + +Returns disktype in the format CDVD_TYPE_xxxx + +// s32 CALLBACK CDVDgetTrayStatus(); + +Returns tray status in the format CDVD_TRAY_xxxx + +// s32 CALLBACK CDVDctrlTrayOpen(); + +Opens disc tray, return 0 on success, else -1. + +// s32 CALLBACK CDVDctrlTrayClose(); + +Closes disc tray, return 0 on success, else -1. + + +Extended funcs +-------------- + +// void CALLBACK CDVDconfigure(); + +Configure the plugin. + +// void CALLBACK CDVDabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK CDVDtest(); + +Returns 0 if the plugin should work ok, else -1. + + +2) FAQs + + * What's the right open/close sequence? + 1. CDVD + 2. GS + 3. PAD1/2 + 4. SPU2 + + * Where to start coding a plugin? + Get an open source plugin, mine are all open source, + so you can freely base on them. + + * Why GSgifTransfer2 exists? + GSgifTransfer2 is used by the XGKICK VU1 opcode, and + it doesn't has a size, the GSgifTransfer is used by he GIF + and the VIF dmas, and it has a size, so that's why :). + +3) Notes + + * CDVDgetBuffer should be used after CDVDreadTrack, + like this: + CDVDreadTrack(time); + ptr = CDVDgetBuffer(); + + but not like this; + ptr = CDVDgetBuffer(); + CDVDreadTrack(time); + + * Errors should be checked for both CDVDreadTrack and CDVDgetBuffer, + and not only CDVDreadTrack. + diff --git a/Docs/Readme.txt b/Docs/Readme.txt new file mode 100644 index 0000000000..20d2c1872a --- /dev/null +++ b/Docs/Readme.txt @@ -0,0 +1,196 @@ + + + + +PCSX2 - A PS2 EMU +------------------ +Here it is. A first try for an ps2 emulator... +Of course it isn't very advance now but there are some stuff here... + + + +Overview +-------- +Well i will try to catch up some questions. +First of all pcsx2 don't run Ps2 games yet! +And of course it is far from doing this. +So pcsx2 don't run GT3, get it? :) +So what pcsx2 is? pcsx2 is a try to emulate sony's beast. +Of course it isn't so easy as it might seems. +So far you can consider pcsx2 as a develop tool althought +i suggest don't use pcsx2 as a tool for writing your ps2dev +stuff :). Consider the opinion that pcsx2 have bugs and we +wrote this emu by reverse enginnering ps2 demos that might +have bugs too :) +Hope you enjoy pcsx2.. + +The Pcsx2 team.. + + +Configuration +------------- + +Cpu Options: + + +Misc Options: + + * Enable Console Output: + Displays the psx text output. + + + * Enable patches + Enable the patches for games.(if they exist). + Might fix some stuff might screw some stuff. + Enable it at your own risk. + + * Enable pad hack. + if your pads doesn't seem to work if you enable that much fix the pads for the specific game. + Warning!! not leave that option checked might broke some other games as well + +Recompiler options: + +* Disable Recompiler (default). It will run with interpreter if it is ON. + Slower but more compatible. + +* Disable Vu recompiler (default). Will disable the vu recompile + (of course if recompile mode is used). More compatible recompiler but slower. + + * Enable reg caching (disabled in 0.6) + Enable the reg caching recompiler (you must have enable interpeter cpu off!) + It is more faster than the default recompiler + + + +Quick Keys: + F1: Save state + F2: Change slot (0-5) + F3: Load State + F8: Makes a Snapshot + + (debugger keys) +---------------- + F11 un/sets Log + F12 un/sets symbol logging + +Status +------ + +Most part of ps2 have been emulate. + +Things that are still missing or uncomplete + +IPU : decoding almost done. Pcsx2 can play *.ipu or *.m2v files but no pss yet +VU : there are several issues with graphics ingames. Still we are not sure if it is GS, VIF or VU problems + but we are looking for it +recompiler: planning for fast reg cache core and recompile of vus . Soon :P + + +and of course a million other bugs that exists and we hope they will be fixed ;0 + + + + + +How you can help +---------------- +If you have any info you think we can use email us, but always ask before +sending files. If you want to help in some other way also email us. + + + +The Team +-------- +Nickname | Real Name | Place | Occupation | e-mail | Comments +--------------------------------------------------------------------------------------------------------------- +Linuzappz | | Argentina | Main coder | linuzappz@pcsx.net | Master of The GS emulation and so many others.. +Shadow | George Moralis | Greece | co-coder-webmaster| shadowpcsx2@yahoo.gr | Master of cpu, master of bugs, general coding... +florin | Florin Sasu | Romania | co-coder | florin@pcsx2.net | Master of HLE. Master of cd code and bios HLE.. +asadr | | Pakistan | co-coder | | Fixing bugs around (FPU, Interpreter, VUs...) +Goldfinger | | Brazil | co-coder | | MMI,FPU and general stuff +Nachnbrenner| | Germany | co-coder | | patch freak :P +aumatt | | co-coder | | a bit of all mostly handles CDVD cmds +loser | | Australia | co-coder | loser@internalreality.com | obscure cdvd related stuff +refraction | Alex Brown | England | co-coder | refraction@gmail.com | General Coding DMA/VIF etc + +ex-coders: +basara -co-coder . Recompiler programmer. general coding +[TyRaNiD] -co-coder . GS programmer.General coding +Roor -co-coder . General coding + + +Additional coding: + +F|RES +Pofis +Gigaherz +nocomp + + +BETA testers +------------ +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever + + +Team like to thanks the Follow people +------------------------------------- +Duke of NAPALM - for the 3d stars demo. The first demo that worked in pcsx2 :) +Tony Saveski (dreamtime) - for his great ps2tutorials!! +F|res - You will learn more about him soon. but a big thanks from shadow.. +Now3d - The guy that helped me at my first steps.. +Keith - Who believed in us.. +Bobbi - Thorgal: for hosting us, for design or page and some many other +Sjeep - Help and info +BGnome - Help testing stuff +Dixon - Design the new pcsx2 page, and the pcsx2.net domain +bositman - pcsx2 beta tester :) (gia sou bositman pare ta credits sou ) +No-Reccess- nice guy and great demo coder :) +nsx2 team - for help to vu ;) +razorblade - for the new pcsx2 logo,icon. +snake - he knows what for :P +ector - awesome emu :) +zezu - a good guy. good luck with your emu :P + + + + +Credits +-------------- +Hiryu & Sjeep - for their libcdvd (iso parsing and filesystem driver code) +Sjeep - for SjDATA filesystem driver +F|res - for the original DECI2 implementation +libmpeg2 - for mpeg2 decoding routines +aumatt - for applying fixes to pcsx2 +Microsoft - for vc.net 2003 :p (really faster than vc6) :P +NASM team - for nasm +CKemu - logos/design + + +and probably to a few more.. + +Special Shadow's thanks go to... +-------------------------------- +My friends : Dimitris, james, thodoris, thanasis and probably to a few more.. +and of course to a lady somewhere out there.... + + + + + +Log off/ +Linuzappz/ shadow / florin / asad/ goldfinger / nachbrenner (others???) + + + + + + + diff --git a/Docs/RemoteDebugging.txt b/Docs/RemoteDebugging.txt new file mode 100644 index 0000000000..339b400b48 --- /dev/null +++ b/Docs/RemoteDebugging.txt @@ -0,0 +1,105 @@ +ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +ºNOTE: 1. this is an internal pcsx2 team document, for developers ONLYº +º 2. lamers/gamers are excluded º +º 3. DECI2 will not run your games:P º +ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +RemoteDebugging +=============== + +This is a new feature available for debugging applications within pcsx2 emu. + Using a remote debugger is not wellcomed unless it is more featured. + Fortunately, there are such debuggers. Currently added support is for win32 + target only; also, only TCP/IP remote connection and only for Sony's DECI2 + app-level protocol. Future addition could be GNU debugger remote support. + +Anyway, pcsx2 has a new menu item that allows one to start a debugging session + by specifying the listen port [default for DECI2 is 8510]. Pcsx2 will act like + a server for the remote debugger. It is set to accept connections on any IP. + For local debugging sessions, use IP=127.0.0.1 aka IP=localhost. On the + other hand, if a pcsx2 would be listening on an active IP in the Internet, + anyone could connect to it;) Only one connection is supported. After the + connection is closed by the client/remote tool, the only thing to do is to + "admire" the log window and then close it/restart the emu. + +So, to start a debug session: + - first start the emu [quite reasonable; because it will be the server]. There + are some issues if you start the client first or if you didn't close ALL the + client subprograms in the last debugging session. + - choose from the menu, Debug->Remote Debugging. A dialog will pop asking for + the port to use. Also, if you have a non-HLE bios selected in the Config box, + ie. a true bios, there will be also an option weather to debug the bios. You + have 2 choices: + -not checked=Run Bios + before any debug is performed a bios run. ie. the emu + will run the bios up to the shell loading or a bit + further, to the moment when all the iop modules are + loaded. You will have then a full environment loaded. + -checked=Debug Bios + nothing is done further and the PC=0xBFC00000. + - after that a connection log window will be shown and you can follow the + connection data exchange. First, the emu is placed in a wait state. + - this is the moment you have to run the client. It will open the connection. + The emu accepts the connection and the DECI2 protocol is on;) + You'll see how the client queries for registers values & memory areas. + - the situation gets complicated since you can do many things from now on: + +Debug bios: + - start with a bios selected and the check box checked (see above). + - PC=0xBFC00000 and you can trace the bios now. Anyway, there is no breakpoints + support for the bios as the client "thinks" you are debugging the real PS2, + so you cannot write to bios area. BTW: the breakpoints are implemented by + patching the code with a BREAK instruction. Since you cannot write such instr + you cannot put a breakpoint on the bios, cannot run to address and so on... +Run bios: + - start with a bios selected and the check box not checked (see above). + - wait till the emu runs the bios...it will take some time. After THAT the + connection log window will be displayed. + - PC=0x82000 or smth like that...you can check the environment set up while + running the bios. The modules window for instance. And various memory + structures. Also, this is the entrypoint of the shell loading. Try to trace + it;) +Debug an application: + - start with HLEbios selected (see above) + - since the debugger (the client) does debug whatever you want to. You can + load the elf to debug with pcsx2 loader (ie. with File->Load ELF file or + from the CDVD). But you will need to know the entrypoint to force it in + remote debugger (set PC to cursor or to address). This way is not recomended. + I like to use the loader of the debugger since it knows to load the source + also if available and does not cause troubles with setting the PC. Also, if + the ELF has symbols, it can run it to main;) + - now, you're on your own. Use step by step, step over, breakpoints, run to + cursor, run to address etc. HAPPY DEBUGGING! + +KNOWN ISSUES and NOTES +====================== + - use CDVDnull or another plugin as you like to have or not a src for cdvd + loading;) + - pcsx2 does not have support to debug the IOP. You can do this now but it is + a hard job. That is due to the fact that PS2 can run every processor + independently (ie. one can be stopped) and pcsx2 cannot. The emu runs either + all the procs or nothing. So, in the debugger, the debugged processor is on + stop and others are "running". When there will be added support for debugging + the IOP, also only one processor will run. + - do not step through the program very fast. Because of the communication speed + and a reentrancy issue, this will get the debugger in a FALSE run state. That + means that the debugger "thinks" that the PS2 (ie. pcsx2;)) is running, + although it is not. The simple solution to this is to press STOP/BREAK button + in the debugger. Notice also that some run states might be also true! When + you are stepping over a big loop...that might take some time, so if you stop + the emu you will get in the middle of the loop:P + - you can also notice the low speed that can also be met in the pcsx2 debugger. + That's because Cpu->Step() is used. + - also, notice that you cannot debug in recompiler mode! ONLY interpreter mode + works! + - IOP modules loading is not supported and the files loaded from host directory + are also loaded in pcsx2 way, ie. from host\ directory; not through remote + debugger. + - if you try to debug the bios and the code is not displayed...scroll down + in order to have only valid addresses on the screen; ie. the top address + to be 0xBFC00000 and in emu communication log there will be no ADDRESS ERROR. + + +=============================== +Florin (florinsasu@yahoo.com) +2003/04/17 diff --git a/Docs/RunCDVD.txt b/Docs/RunCDVD.txt new file mode 100644 index 0000000000..abcede508c --- /dev/null +++ b/Docs/RunCDVD.txt @@ -0,0 +1,86 @@ + +RunCDVD - New feature explained +=============================== + +Q: What CDVD stands for? + +A: It is a short form for CD/DVD i.e. CD or DVD. + +---------------------------------------------------- + +Q: Can I run games? + +A: What do you mean by games? + There are two types of games: commercial ones and homebrew ones. + There are also two types of demos: from magazines and homebrew. + Homebrew SW will run first as they are simpler and are open-source sometimes. + +---------------------------------------------------- + +Q: Can I run commercial games? + +A: Yes, but this answer is not good for you:P + You cannot play them... + Technicaly, the game starts but it does not go very far, + because this is only the beginning... + +---------------------------------------------------- + +Q: So, what's the deal then? Is there any game that run? more? + +A: Yes, but as far as we know, not any comercial game. + Homebrew iso version of PSMS runs ok. + Also we cannot test with all the games as we don't have them all:P + +---------------------------------------------------- + +Q: When can I play game X ? + +A: Dunno, only time can say that... + We only added the CDVD loading option for now. + You will have to wait for another version of the emu to see any screenshot. + +---------------------------------------------------- + +Q: How do I run a CD/DVD game or iso/bin? + +A: You need a CDVD plugin. + Get the CDVDbin for Windows & CDVDlinuz for Linux + from http://pcsx2.ngemu.com (Download section) or from http://www.ngemu.com + Place it in Plugins directory. Run the emu and in configure dialog choose + that plugin. Then Run->Execute. When using the CDVDbin plugin + you will be promted to choose a file to use. + Select the iso or the bin of the game you own. + (To test that use psms.iso) + +---------------------------------------------------- + +Q: I have the game X on CD/DVD. What's the iso/bin stuff anyway? + +A: Well, if you have a game on CD/DVD and a bad CD/DVD drive, + you can backup it on the harddisk with a CD/DVD recording program or a simple + iso/bin ripper. That program will make an image of the CD/DVD disc + on the harddisk and you can use that image with the CDVDbin plugin. + +---------------------------------------------------- + +Q: What's the difference between .iso and .bin formats? + +A: Bin is an image with raw sectors of 2352 bytes. + Iso contains only the data part from a CD sector; ie. 2048 bytes + +---------------------------------------------------- + +Q: I have more questions. Where are the answers? + +A: First of all, think twice before asking a question. + It might be already answered or the answer is toooooo simple. + Also, there can be more questions that i missed. Use the PCSX2 forum + on http://www.ngemu.com for that. Thank you! + + +=============================== +Florin (florin@ngemu.com) + + + diff --git a/Docs/ToDo.txt b/Docs/ToDo.txt new file mode 100644 index 0000000000..a8a595c7f9 --- /dev/null +++ b/Docs/ToDo.txt @@ -0,0 +1,22 @@ +To do for Pcsx2: + * Fix threads, semas & events (linuzappz, Florin) + * Deci2: iop debug (since pcsx2 cannot run only one processor) (Florin) + tty notifications + * Continue RunCDVD option for PS1 exes loading. + * Continue Bios emulation. (linuzappz) + * Continue Recompiler. (linuzappz, basara) + * Fix bios execution. (linuzappz) + * Recheck TLBS. + * Continue HW stuff. (linuzappz) + * Fix VU code. (shadow) + * Check MMI.c. + * Check FPU code. + * Implement remaining COP0 opcodes. + * Deci2: + -speed up execution with Cpu->ExecuteBlock(); + -fix reentrancy problem with threads (if pressed step button to soon, + you get a false run state: the emu is on pause, but the debugger + thinks that it is running) (solution: critical zones) + -add drfp support [i guess this will not be done as it is not really needed] + -add iop files load&run support (iloadp; not a priority also) + (Florin) diff --git a/Docs/Translating.txt b/Docs/Translating.txt new file mode 100644 index 0000000000..b936bb0dea --- /dev/null +++ b/Docs/Translating.txt @@ -0,0 +1,24 @@ + Translating PCSX2 + ----------------- + +Just some small notes for translators. + +PCSX2 translations are based on the gettext library: +http://www.gnu.org/software/gettext. + +The main file to translate is pcsx2.po located at the +'Intl' dir, note that you must place the translated +strings over the msgstr and leave untouched the msgid. + +To test the translation use the msgfmt.exe utility to +convert the translated pcsx2.po file to a pcsx2.mo file +with this command: 'msgfmt pcsx2.po -o pcsx2.mo', after translating +the file please send it to us and please ask before +translating it, maybe someone has already started it +for your language. + +If you have any problems contact us and we'll try to +help you. + + linuzappz + diff --git a/Docs/What_Is_Host.txt b/Docs/What_Is_Host.txt new file mode 100644 index 0000000000..5671a49383 --- /dev/null +++ b/Docs/What_Is_Host.txt @@ -0,0 +1,45 @@ + +I will try to explain in sorta how HOST is working.. +----------------------------------------------------- + +Ps2 have the ability to use loader also other than cd-rom. +That is done through special syscall. Of course the file that +you load must support that.. + +Basically we wrote that for PSMS1.2 + +As you can see in the psms1.2 zip there is a file called psms-naplink.elf. +Well that is basically created from sjeep (hi sjeep) for be able to +use psms through your USB naplink to your ps2. (so no need to burn a cd) +Well pcsx2 does exactly that. Emulate Host +client (host is your pc, +client is your ps2). + +So how is work? +--------------- +Imagine that HOst is your cd-rom . +For psms e.g +place FILES.TXT + roms in folders that specificate in files.txt and you are +ready.. + +e.g + +Host +FILES.TXT +-ROMS1 +--Alienstorm.sms +--IamLamer.sms + +I think you get the Idea... +For more questions mail me..(shadow@pcsx.net) + +About +----- +This doc has been written from shadow... +Host support was added kindly to pcsx2 by Linuzappz +Thanks to sjeep for his psms1.2 emu and his support.. +Also thanks to Keith,bobbi,thorgal,akumax,now3d and probably to some more... + +Log off +shadow/linuzappz + + diff --git a/Docs/WhatsNew.txt b/Docs/WhatsNew.txt new file mode 100644 index 0000000000..fb4178a1d8 --- /dev/null +++ b/Docs/WhatsNew.txt @@ -0,0 +1,598 @@ + ********************************* + *What's new in pcsx2 v0.8 * 13th release + ********************************* + +General +------- +Compatibility has been increased since last release. More games go ingame now and 3d is okay in most of +them. Vurecs improved and speeded up a lot (buggy in many causes so use the simple rec for compatibility) +and IPU should work in some cases.(e.g VF4) + +CPUs +---- +Fixed QFSRV/MTSAH/MTSAB +Fixed SBUS IRQ at iop +Fix for end chain mode at vif +Fixed SPR0 chain mode +Fixed intc/dmac interrupts that gets cleared right away +Added offset/difference UNPACK modes in vif +VIF irq by vifcode seems ok now +Added interleave mode for SPR +Fixed UNPACK V4_5 with mask +Fixed small bug over VIF1 dma FIFO +VIF1 doens't clears str on MFIFO +Fixed some MFIFO bugs in both GS/VIF1 +Fixed bug in REF/REFS dma at VIF1/GS MFIFO + +IPU +--- +Finally fixed IPU. Mpegs and IPU streams run so do PSS files +Quality of ipu playback improved + +PLUGINS +------- +Added GSsetCSR +added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose to cdvd + +CDVD +---- +Added some more debug info to CDVD +Fixed cdReadKey function to emulate correctly. +Modified GetToc stuff in cdvd to support dvds +cdvdTD uses lsn now +Fixed NVM (eeprom) access from cdvd stuff +Added reading of mecha version from an external file +Fixed raw dvd sector readng for dvd9 discs (otp and ptp) +Added hw-reg read/write for DecSet register 0x1f40203A +Made cdSeek change the current cdvd sector +Fixed NReady busy stuff + +Memory +------ +Added more memRead/Write funcs for speed + +VUS +--- +Fixed bug in branch address in vus +Implemented MFLAG for VU0 +Fixed some iVUmicro bugs +Fixed some VPU-STAT related issues +Fixed vu flushing over vuExecMicro +Fixed some pipelines bug within VU1,VU0 +Reworked MAX/MINI +Fixed VU's JR/JALR/BAL,ISUBIU +Added EFU pipeline to VUmicro +Fixed DIV/RSQRT exceptions + +GUI +--- +Some improvements on interface. +Added placetopatch == 1, which means patches will be applied every vsync + + + ********************************* + *What's new in pcsx2 v0.7 * 12th release + ********************************* + +GENERAL +------- +Memcards and pads should work okay now. More compatibility earned since so many things +have been fixed from previous release :) + +VIF-VUS +------- +VIF-FIFO transfers seems to work better +VU1 regs now are mapped to VU0 mem +Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2 +Fixed vu branch negative overflows +VU D/T flags are handled now +VU pointer gets aligned now + +PLUGINS +------- + +Added Firewire plugin protocol + +SPU2 +---- +Fixed SPU2async cycle +SPUdma timings changed to 80 + +CDVD +---- +Implemented ReadNVM/WriteNVM +BCR now decrements for each cdvdReadSector +Fixes to SCMD's +ReadILink/GetMecaconVersion are really implemented +CdReadConfig/CdWriteConfig now uses NVM + +Interface +--------- +sstates now use CRC +Added IOP disasm in the debugger +Added rom2/erom support +Added Patch Browser for win32 + +IPU +--- +Several changes for IPU + + +HARDWARE +-------- +Fixed bug IOP counters +Fixed some bugs over interrupts and exceptions +Newer bios will now work with pcsx2. Pads fixed, more compatibility +Fixed SIF0/1 when fifo got filled up +Fixed EXL bug +Fixed SIF SMFLAG/MSFLAG +Fixed MCDS + + + + ********************************* + *What's new in pcsx2 v0.6 * 11th release + ********************************* + +General +------- +pcsx2 is 3 years old. Happy birthday pcsx2 :) +Now you can run even more games. some 3d games should work too . so enjoy :) + + +CPUS +---- +Recompiled VUs. Needs work but some stuff might work okay now +Fixed bug in Vif.c, masks hopefully are ok +Fixed alot of bugs in VUs, hopefully some stuff will now work as it should +Added Interlock for CFC2/CTC2 +Improvements to TLB code +Restructured VU code and VIF. Fixed stuff in Interpreter and added CTC2 VU1 Microinstruction caller +Fixed UNPACK modes in VIF, the Indeterminate fields are now set to 1 by default +VUflags now should handle overflow/userflow ok + +Hardware +-------- +Fixed DMA8 +Fixed bug in GS for CSR stuff +Fixed savestates +Fixed several SIF bugs +FIFO is now really 128bit as it should be +Added code for dma interrupts +Added some scmds to CDVD +Improved and fixed sio2 stuff +Modified the DEV9irq stuff +loadElfFile now reads the whole file first +DMA4/7 interrupt timings are more accurate now +Patches names are now using crc + +GUI +--- +Memory patcher (supports only 32bit patches so far) +Fixed Bios Detection for HK Bios + +PLUGINS +------- +ADDED usb plugins + + + ********************************* + *What's new in pcsx2 v0.5 * 10th release + ********************************* + +General +------- +A release that make you look things more promising. Several games can boot now and plenty of them can reach even ingame. +There are still big issues with graphics but many improvements have done from 0.41. Some games that now can reach ingame +are: +wild wild racing PAL (with patches) +Street fighter ex3 PAL (with patches) +Le Mans 24 Hours (24 Heures Du Mans) PAL (with patches) +V-rally 3 pal (with patches) + +and probably a lot more :) + + + +CPUs +--- +Fixes to VUs +Handle for the EDI flag at ERET(cop0) +New improved cpu detection routine +Commented D/T flags for VUmicro +fixed some FPU bugs in recompiler +fixed PCPYLD in interpreter +Add compiler blocks for vu0, vu1 and few instructions +Several other fixes in cpu cores +Reg caching recompiler (not enable in 0.5 ) + +Debugger +-------- +Fixed Debugger/rdebugger (there are still some issues) + +Memory +------ +Added TLB exceptions +Fixed IOP mem accesses from EE Memory +New memory routines + +VIF +--- +Fixed VIF Transfers to include MARK reg in VIF0 aswell. +FIFO for VIF0/1 now works +More improvements to VifDma +Improved VIF for transfers in parts +FiFo VIF1 can read data now + +IPU +--- +Fixed IDEC bitstream decoding. Now, all *.ipu files should work fine +bug fixes to IPU + + +Hardware +-------- +Fixed clock in bios +Fixed MFIFO for GS dma +CDVDgetTD function need a 2nd parametre (new cdvd plugins needed!!) +cdgetTOC + cdReadSubq +HSync stuff, and better CSR/IMR handling +Implemented mskpath3 / m3r flags +Fixed VU memory64 writes masks +Implemented INTC_STAT/MASK and DMAC_STAT for 64bits +Added/fixed SCMDs (2,3,1A) in cdvd +Vif0/1 regs are now mapped to hardware +Fixes in sio, sio2 +Destination Chain for SPR0 dma and added Vif masking +Now pad2 works in lle mode [tested with bios browser] +New SCMDs and MC commands +Fixed dmaIrq's for Source Chain mode +Fixed ret DMA op +Added a base interrupt delay for the dma7 (spu2) +Fixed pads. Now it should work okay most of the times +Changed the way we handle SPR TTE transfers + +MISC +---- +Added the possibility to load the System.map from ps2linux +Added patching system. *pnach files are used now +Added dev9 plugins +Savestates + + + ********************************* + *What's new in pcsx2 v0.41 * 9th release ( Update ) + ********************************* + +General +------- +This release fixes a minor issue with the DVD iso's not booting, as of now DVD iso booting +is fixed so please try all your games again !:) + +Hardware (lle) +-------- +Fixed bug in CDVD code for DvdReads, now DVD iso's should boot just fine. + + + ********************************* + *What's new in pcsx2 v0.4 * 9th release + ********************************* + +General +------- +This release is how we wanted the first pcsx2 release to be. Finally bios is working so +many things can happend from now on. Also "Bust a Move" seems to work and other games +like Kengo 2 goes much further. All of course is done in LLE now :) . + +CPUS +---- +fix the recompiler bug that made recompiler not to work in pcsx2 0.3 +new vu code. VU0 macromode should be perfect now. +new optimaze code for fpu +Rewrote VIF once again +bug fixes to MMI +reorganize recompiler + + +DMAS +---- +Improved SIF0,SIF1,SRP1 +Added IPU0,IP1 dmas + +IPU +--- +Added decoding and commands. Some samples are working. NO pss support yet! + +IOP +--- +improved the IOP stuff.IOP is functional under bios execution :) + +HLE +--- +more WIP in Threads .Much better now +more WIP in padman. + + +Hardware (lle) +-------- +ADDED SPU2 functions. SPU2 is now possible if someone implement a SPU2 plugin. +Changed a bit the GS protocol. Gs plugins need to modificate in order to work with 0.4 +SIO2 added .Pads seems to work . Memcard partial functional +CDVD emulation added. +IOP rootcounters fixed +IOP dmas implemented +MFIFO implemented + + + +General +------ +Fixed elf loader + + + ********************************* + *What's new in pcsx2 v0.3 * 8th release + ********************************* + + + +General +------- +This version of pcsx is the first that shows ingame progress from 1 game "Sven Goran's World Manager 2002".IT is the first +ps2 emu that reaches ingame :) . Also this version have Deci2 support (usefull only for developers althought) and several +bugs have been fixed. Enjoy ;) + + + +GUI +--- +-Added MiltuLingual support( English,Catalan,German,greek,italiano,romanian,spanish) + +CPUS +---- +-Fake BC0 opcodes in cop0 +-Trap instructions fixed in interpreter +-Fixed some fpu bugs in interpreter +-Fixed MMI bugs in interpreter +-VIF1 cmd now handles the i bit, still not 100% correct +-VIF1dma now handles 'from Memory' transfers +-More Unpack case in vif +-fixed several VIF1 bugs +-VIF0 fixed also + +Hardware +-------- +-8 bit DMAS +-mem128 read/write routines +-Implemented latency interrupt thingy +-Fixes to rootcounters +-FIFO fix +-IOPmem fix +-optimaze gs dma + +Debugging +--------- +-DECI 2 Protocol !! +-fix some stuff in pcsx2 debugger +-add cpu ops debug in debugger +-Logging to STDOUT added +-add more memory mapping for EE and IOP + +HLE +--- +-rewrote of HLE code for pads (padman-xpadman). This will solve some pad problems +-rewrote the HLE code for Loadmodule +-New INTC handling in HLE bios +-Implement VSyncSetFlag in HLE bios +-Added memory dummies in mcserv. Now memcards wil be appear as functional. +-sceCDReadIOPm in CDVD HLE +-Added dummy handles for mtapman901/3 +-new Threads at BIOS HLE. Still not finished + + + + ********************************* + *What's new in pcsx2 v0.2 * 7th release + ********************************* +General +------- +pcsx2 have now a more speedy recompiler using 3dnow-3dnow2-sse instructions. Vu macromode +have been recompiled with 3d now instructions so you can see more speed there if you have a +cpu that supports 3d now. The most speed is possible with an Athlon XP cpu or a Althon 4 mobile +More support for sse or probably for sse2 soon :) + + + +rewrite of MMI +fix bugs in fileio +fix counters +new thread HLE code +fixes to CDVD HLE code +fixes-adds to VU code More vu opcodes +add some more cpu opcodes +more ipu code +add 3dnow-3dnow2-sse instructions to recompiler + + + ********************************* + *What's new in pcsx2 v0.1 * 6th release + ********************************* + +General +------- +PSMS cd version seems to work. Pgen starts to work also.. (no roms seems to working althought) +and some games might boot now... This is the first ps2 emu that boots cds :) + +GUI +--- +Added command line parsing for main's argc +Added ps2 bios check for config dialog + + +Memory +------ +Some more adds to memory maps + +CPUS +---- +Implement VU flags + some more vu0-vu1 opcodes +Fix some VIF unpack cases +Some more opcodes to R5900 + +HLE +--- +better HLE + + +RPC services for +014D704Enaplink +0B001337cdvd +80000001fileio +80000003sysmem +80000592cdvdfsv +80000597cdvdfsv +80000595cdvdfsv ++for some more but mostly dummies + +CDVD iso parser (thanks Sjeep - hiryu) +support for SJDATA file system + + + ********************************* + *What's new in pcsx2 v0.042 * 5th release + ********************************* + +GENERAL COMMENTS +---------------- +Micromode works at the release. Also some more macromode demo should +work on this release.Enjoy ;) +NOTE: Logging has been disable from the release. If you need it +Mail me ( shadow@ngemu.com) + + +GUI +--- +-ADD CDVD plugin (partially) +-change a bit the controller plugin protocol +-change a bit the GS plugin protocol (for the VUmicromode transfers) + + +CPUS +---- +-FIXES to R5900 +-FIXES to FPU +-More work in recompiler +-ADDS+fixes opcodes for MMI +-Rewritten/updated iop code +-More work to micromode (vu0-vu1) + + + +DMA +--- +-More to VIFS DMA +-More to SIFS DMA + + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.038 * 4th release + ********************************* + + +GENERAL COMMENTS +---------------- +Vu0 appears functional now. (Most of the causes ) + + +CPUS +---- +Fixes to main R5900.Many opcodes fixed ( thanks Goldfinger) +Fixes to FPU +Add some Framework for the IPU +Add some more opcodes to the recompiler including FPU opcodes + + +Debugger +-------- +Logging system + + +BIOS HLE +-------- +some support for sjpcm.irx +Fixed fileio for dummy files + + +----------------------------------------------------------------------- + + ********************************* + *What's new in pcsx2 v0.036 * 3rd release + ********************************* + + +Debugger +------- +-Add VU0 - VU1 register window +-Add VU0 macromode in disasm (still not finished) +-Added support for Symbols + +GUI +--- +-Add SPU2 interface (very partial) +-change GS specifications a bit + +CPUS +---- +-Fixed some bugs in R5900.c +-Improve recompiler +-Add VIF0 - VIF1 (very partial) +-Add more VU0 macromode instructions +-Add IOP proccesor (partial) +-Add More opcodes in MMI +-better COP0 emulation (more tlbs) + +DMA +--- +-add Stratchpad DMAS +-add VIF dmas +-add SIF dmas (very partial) + +Memory +------ +-Total rewrite to support more HW + +BIOS HLE +-------- +Many more syscall is hle now. Compatibility increase a lot + + + +General +------ +Many stuff that we are not able to explain them in details :) + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.031 * 2nd release + ********************************* +-New icon +-New logo +-Some startup work on VU0.Many VUO macromode opcodes +-Some more opcodes in the main cpu. MFSA,MTSA,SQC2,LQC2 +-More opcodes to the MMI. +-Finished R5900 FPU. +-pad emulation using HLE.. both pad1 + pad2 +-more fixes to Recompiler (still far from finish) +-add the 4 Couters(partial) +-add FIFO registers +-Add support for HOST + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.026 * 1st release + ********************************* + +FIRST RELEASE ALL ARE NEW :) + diff --git a/Docs/devblog.txt b/Docs/devblog.txt new file mode 100644 index 0000000000..de2b9a4ac1 --- /dev/null +++ b/Docs/devblog.txt @@ -0,0 +1,272 @@ +Developers Blog +=============== + +This file is mainly an R&D document containing developers findings. The aim is + to have it as much accurate as possible. Each item has to contain a number(ID), + the name of developer, revisions history and a short description. +Also, this document will serve as a pinboard - will contain coding rules, + explanations on implementation of different parts of the emulator, suggestions, + questions and ideas. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 4 +[name] Florin +[desc] PS2 info dumping project +[hist] 2006-05-08 initial version + +The emulator needs some information from a Playstation2 console. +We used to require the 'bios' software. In order to get better results + more and more information was needed. So here are some guidelines + on what we need and what we don't need from the console. +Also, a new dumper and handling of these infos in the emu are in work. + +a. The so-called 'bios', is actualy rom0 found in consoles, devkits, + test-kits and PSX at address 0xBFC00000 on both EE and IOP. + [!] Note that on 75xxx the EE side bios mismatch zone fields, + so it is recomended to make a IOP side dump. +b. Rom1 and Erom contain DvdPlayer related software and are located + starting with 0xBE000000 on PS2s from 18000 and up. Over various + versions, the size of rom1 and size and position of erom changed. + They used to be dumped separately, the new dumper will simplify this, + there'll only one file containing both rom1 and erom (2M or 4M). + [!] Note that on 70xxx and 75xxx (PStwo's) the dumping of erom from EE + is not possible, the correct dump is done only from IOP! + [!] rom1 and erom are identical for same generation for all zones. + In order to be able to run the dvdplayer code in the emulator, it needs + to be pre-decrypted. EROMDRV and DVDELF will have some 'decrypt' patches. +c. NVM (Non Volatile Memory) is 1K of code and provide valuable info about + console model and region. 10000 and 15000 don't contain the model name. + PStwo's contain the zone codes making possible to have a single version + of the rom for all zones. +d. Rom2 is found only in Chinese PS2s (50009, 70009...) and contains + a font file: GB18030. It is located at 0xBE400000. It was (w/o + justification) assumed that it is as big as rom1. There is no need to + dump it on any other console than chinese. The size is to be calculated + from the filesystem (as rom0 and rom1, it has romfs). +e. BBA (BroadBand Adapter) info is not needed to be dumped. At least not + for the emulator itself, maybe for the DEV9 plugin. Anyway, it's just + a MAC address that can be made up. +f. The current dumper is reading CDVD Mecha version. This will be replaced + by a more complete information file that will contain the following info: + from [EE] + CPU revision - revision code from COP0->PRId register + easier read from (u16)GetCop0(15) + high byte is 0x2E for EE + low byte is: high nibble major, low nibble minor of revision + FPU revision - revision code from COP1->control register 0 + same description as for cpu PRId + VUs revision - hum, i'm not aware of any revision for them :( + VUs memory - local and micro memory sizes are not detected + GS revision - upper halfword in CSR register + high byte is ID = 0x55 + low bytes is major.minor (per nibbles) + GS mem - is 4M + IPU revision - hum, i'm not aware of any revision for IPU :( + Caches - instruction and data cache sizes are read from + COP0->Config register + easier read from GetCop0(16). + MEM - total RAM available + easier read with Syscall +127 - GetMemorySize() + the values are: 32M for console and test-kits, + 128M for devkits and 64M for PSX + the size is not roughly detected. As devkits have multiple + boot modes (128M or 64M). + from [IOP] + CPU revision - revision code from COP0->PRId register + high byte seems to be 0 + low byte is major.minor (per nibbles) + initial japs have major=1, + most of the consoles have major=2, + 75xxx have a new IOP processor with major=3 + Caches - are known to be 4K-I$; 1K-D$ + 0xFFFE0130 is CACHE_CONFIG register... + MEM - total RAM available + easier to read with QueryMemSize() + the values are: 2M for consoles and test-kits, + 8M for devkits and PSX + again, the size is incorrectly read :) + SPU mem - 2M (any method of detection?) + CDVD mecha - version of CDVD controller + Scmd 0x03 with subcode 0x00 (outsize=4) + the first byte is the MG-encryption code + second is major, third is minor, fourth is [2b completed] + meka - i don't know; not supported on early consoles + Scmd 0x03 with subcode 0x90 (outsize=1+1) + DEV9 revision- type of DEV9 device: 0x2x for PCMCIA, 0x3x for EXPBAY + *(vu16*)BF80146E + USB OHCI rev - Hc_revision of the OHCI controller + *(vu32*)0xBF801600 + ILINK rev/id - I'm not sure of this one, on ps2's that don't have + firewire anymore, the value is 0xFF; on 10000 is random + *(vu32*)0xBF808480 and *(vu32*)0xBF808500 (looks like mirror) + +g. The dumper will sign the dumped content, so John Doe cannot play easily + with the bios data ;) The emu works correctly with good data/food. + +h. I'm thinking of a method to check for modified content (dumps made with a + chipped console). Probably, it will be done in the emu and presented as a + warrning. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 3 +[name] auMatt +[desc] PS2 NVM Data not 100% +[hist] 2006-05-07 initial version + + ³v0-v11 ³ v12- ³ Bits ³ Bytes º +ÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍ͹ +ÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍ͹ +PS1 Disc Spd ³ 0x300 ³ 0x2c0 ³ ³ º +PS1 Texture ³ 0x300 ³ 0x2c0 ³ ³ º +Video Output ³ 0x300 ³ 0x2c0 ³ ³ º +SPDIF ³ 0x310 ³ 0x2c0 ³ 0 ³ º +A/R ³ 0x310 ³ 0x2c0 ³ 1 & 2 ³ º +Language ³ 0x311 ³ 0x2c1 ³ All ³ º +TimeZone ³ 0x312 ³ 0x2c2 ³ ³ º +Summer Time ³ 0x312 ³ 0x2c2 ³ 3 ³ º +Time Format ³ 0x312 ³ 0x2c2 ³ 5 ³ º +DateNotation ³ 0x312 ³ 0x2c2 ³ 6 & 7 ³ º +TimeZone ³ 0x313 ³ 0x2c3 ³ All ³ º +TimeZone ³ 0x315 ³ 0x2c5 ³ All ³ º +Model Number ³ 0x1a0 ³ 0x1b0 ³ ³ 16 º +Console ID ³ 0x1c8 ³ 0x1f0 ³ ³ 8 º +ILink ID ³ 0x1c0 ³ 0x1e0 ³ ³ 8 º +Date Stamp ³ 0x180 ³ ³ ³ 16 º +Date Stamp ³ 0x1e0 ³ ³ ³ 16 º +Date Stamp ³ 0x1f0 ³ ³ ³ 16 º +Rem. Control ³ ³ 0x2c4 ³ 5 ³ º +Checksum ³ 0x31f ³ 0x2cf ³ All ³ º + +Checksum is calculated by the previous 15 bytes added together, then ANDed with 0xFF + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 2 +[name] Florin +[desc] PS2 bios versioning +[hist] 2006-04-30 initial version + +MG zone - the MagicGate decryption zone. You can find the code as one of the bits + in the byte at offset +1C in MagicGate encrypted files +PS1 drv - the letter for PS1VERx files in PStwo rom0 +ROMVER - has the following format VVvvZTYYYYMMDD in 14 bytes + VV, vv are the version of the bios in BCD + Z is zone code, see below + T is type of the console: C - consumer console, D - devkit/test console + YYYYMMDD is date of the bios + - BxDATA-SYSTEM, BxEXEC-SYSTEM, BxEXEC-DVDPLAYER uses Z code in place of 'x' + I: default, Japan; A: Usa, Asia; E: Europe, Oceania, Russia; C: China +VERSTR - the code from that file in rom0 +OSDVER - VVvvZlng is the format of the file for scph5xxxx. in PStwo the last 4 letters + are read from NVM, offset +180 7 chars (ROMVER:1|OSDVER:4|VERSTR:1|DVDID:1) +mecha - version read from CDVD SCmd 0x03:0x00 + +The following table is far from complete... + + ³Japan ³ USA ³AusNz ³ UK ³Europe³Korea ³ HK ³Taiwan³Russia³China ³Mexic º +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +MG zone ³ 0/J ³ 1/U ³ 3/O ³ 2/E ³ 2/E ³ 4/A ³ 4/A ³ 4/A ³ 5/R ³ 6/C ³ 7/M º +PS1 drv ³ J ³ A ³ E ³ E ³ E ³ H ³ H ³ H ³ E ³ C ³ A º +ROMVER ³0 J ³1 A ³2 E ³2 E ³2 E ³1 H ³1 H ³1 H ³2 E ³3 C ³1 A º +VERSTR ³ J ³ A ³ E ³ E ³ E ³ J ³ J ³ J ³ E ³ J ³ A º +OSDVER ³0 Jjpn³1 Aeng³2 Eeng³2 Eeng³2 Eeng³5 Kkor³6 Htch³6 Htch³4 Rrus³3 Csch³ Aspa?º +ÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +v0 scph³10000 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³0.12.0ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ver³0100JCÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + date³000117ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + scph³15000 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³0.18.0ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ver³0101JCÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + date³000217ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + scph³18000 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³0.22.0ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ver³0120JCÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + date³001027ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +v1 scph³30000 ³30001 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +v2 ³30000 ³30001 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +v3 ³30000 ³30001 ³30002 ³30003 ³30004 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +v4 scph³30000 ³30001 ³30002 ³30003 ³30004 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ver³ ³ ³ ³0120EC³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + date³ ³ ³ ³000902³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ³35000 ³35001 ³35002 ³35003 ³35004 ³35005 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +v5 ³30000 ³30001 ³30002 ³30003 ³30004 ³30005 ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + scph³30000R³30001R³30002R³30003R³30004R³30005R³30006R³30007RÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³0.32.0³ ³ ³2.32.0³ ³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ver³0160JC³ ³ ³0160EC³0160EC³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + date³011004³ ³ ³011004³011004³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +v6 ³ ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +v7 scph³37000 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + ³39000 ³39001 ³39002 ³39003 ³39004 ³39005 ³39006 ³39007 ³39008 ÃÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³ ³1.36.0³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄĶ + ver³ ³0160AC³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄĶ + date³ ³020207³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÄÄĶ + ÃÄÄÄÄÄÄ´39001NÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´39010Nº +ÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +v8 scph³39000 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´39006 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ + mecha³0.38.0³ ³ ³ ³ ³ ³ ³ ³ ³ ³ º + ver³0160JC³ ³ ³ ³ ³ ³ ³ ³ ³ ³ º + date³020426³ ³ ³ ³ ³ ³ ³ ³ ³ ³ º +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +v9 scph³50000 ³50001 ³50002 ³50003 ³50004 ³50005N³50006 ³50007 ³50008 ³50009 ÃÄÄÄÄÄĶ + ÃÄÄÄÄÄÄ´50001NÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´50010Nº + ³55000 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´55005N³55006 ³55007 ÃÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +ÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄĶ +v10 scph³ ³50001 ³50002 ³50003 ³50004 ³ ³50006 ³50007 ³ ³50009 ³50010 º + mecha³ ³ ³ ³ ³ ³ ³4.54.0³4.??.0³ ³6.??.0³ º + ver³ ³ ³ ³ ³0190EC³ ³0190HC³0190HC³ ³0190CC³ º + date³ ³ ³ ³ ³030623³ ³030623³030623³ ³030623³ º +v11 ³ ³ ³ ³ ³50004 ³ ³ ³ ³ ³ ³ ºMexic USA +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍÎÍÍÍÍÍÍÑÍÍÍÍÍÍ» +v12 scph³70000 ÃÄÄÄÄÄÄ´70002 ³70003 ³70004 ³70005 ³70006 ³70007 ³70008 ³70009 ÃÄÄÄÄÄÄ´70011 ³70012 º + mecha³ ÃÄÄÄÄÄÄ´3.62.0³2.62.0³2.??.0³ ³4.64.0³ ³5.??.0³ ÃÄÄÄÄÄÄ´ ³1.60.0º + ver³0200JCÃÄÄÄÄÄÄ´0200EC³0200EC³0200EC³ ³0200HC³ ³0200EC³ ÃÄÄÄÄÄÄ´ ³0200ACº + date³040614ÃÄÄÄÄÄÄ´040614³040614³040614³ ³040614³ ³040614³ ÃÄÄÄÄÄÄ´ ³040614º +v13 scph³ ³70001 ³70002 ³70003 ³70004 ³ ³ ³ ³ ³ ³ ÌÍÍÍÍÍÍÏÍÍÍÍÍͼ +ÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͹ +v14 scph³75000 ³75001 ³75002 ³75003 ³75004 ³75005 ³75006 ³75007 ³75008 ÃÄÄÄÄÄÄ´75010 º + mecha³ ³1.66.0³3.66.0³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄ´ º + ver³ ³0220AC³0220EC³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄ´ º + date³ ³050620³050620³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄ´ º +ÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄĽ + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 1 +[name] Florin +[desc] CVS management rules +[hist] 2006-04-30 initial version + +Please do not commit on CVS temporary files or those made by development tools + (IDEs). Eg: *.suo/aps/opt/plg/ncb/exp +Keep it clean and before commiting a new module see the previous structure and + naming rules. If unsure about how to do any opperation please ASK. please ASK! +There's no rush ;) +Also, I'm considering switching to SVN, as CVS seems to be *abandoned* by + sourceforge.net +Any change to sources has to be commited to the public CVS. The risk of + stealing is faced by any open-source developer - the difference is the + quality! The original will always stand up ;) +Try not to break the source by your patches. Although linux and 64-bit versions + are not maintained atm, your changes should be done with all versions in mind. +Happy coding :) diff --git a/Docs/efpchangesv0.9linux.txt b/Docs/efpchangesv0.9linux.txt new file mode 100644 index 0000000000..f32471b9b4 --- /dev/null +++ b/Docs/efpchangesv0.9linux.txt @@ -0,0 +1,112 @@ +Changes made to make v0.9 work in Linux: + +Common.h - PCSX2_MULTICORE undefined. + In my version of linux, spinlocks are bleeding edge calls, and not +implemented as standard. There may be a #define that can be used, but +as it would likely include either a kernel rebuild or thread library, +I hadn't bothered. + +Misc.c - SYNC_LOGGING undefined + I suspect because of PCSX2_MULTICORE being undefined, "g_mtxLog" +didn't get defined either. + +Interpreter.c - all "_controlfp" calls commented out. + I suspect a .h file is missing for the above call. + +Vif.c - Control of MMX, SSE, SSE2 (and SSE3) instructions. + Presence of the above CPU intrinsic calls can be detected using +__MMX__, __SSE__, __SSE2__, and __SSE3__. Header dependancies are +as follows: + __MMX__ can stand alone. + __SSE__ needs __MMX__. + __SSE2__ needs __SSE__ (which needs __MMX__) + __SSE3__ needs __SSE2__ and __SSE__ (which needs __MMX__) + Each of these flags can be used to load their own set of functions +as well as loading all functions in the dependant headers... + __MMX__ - #include + __SSE__ - #include + __SSE2__ - #include + __SSE3__ - #include + Since no tests for the above flags were conducted before loading +emmintrin.h, I blocked out that section of code with an "#if 0" line. + +IPU/IPU.c - After finding out that a dozen mutexes were set here without + PCSX2_MULTICORE blocking, I went back to Common.h and turned back on +PCSX2_MULTICORE. I knew now I would have to hunt down all instances of +spinlocks and replace them with straight mutexes. + R5900.h lines 150-167 - Spinlock defines commented out. + R5900.c lines 32-38 - Spinlock define commented out. + +IPU/IPU.c - invalid initializer - NULL on pthread_mutex_t / pthread_cond_t + Separated the variables initialized. Hunted up valid initializers in +pthread documentation in Linux. + __declspec() - In Common.h, I told Linux to ignore all references to this +function. #pragma pack(16) and/or __attribute__ ((?)) might be a better +choice for this. A couple of compiler flags also control byte alignment. +For dynamically allocatable blocks, memalign() might work. + Note: for 64 bit compiles (like athlon64), 16 byte alignment is assumed. + EBUSY undeclared - This relates to the define DESTROY_MUTEX in Common.h. +Included in Common.h so EBUSY is defined. + __forceinline - placed "#define __forceinline inline" in Common.h as Linux +has no equivlent (that I know of) to this. + +IPU/Idct.o - no target + Moved to IPU/mpeg2lib. Adjusted Makefile to find it. + +IPU/Mpeg.o - no target + Moved to IPU/mpeg2lib. Adjusted Makefile to find it. + +VifDma.c - See Vif.c for complaints about __SSE__ detection. + +Linux/Config.c - no member "PadHack" + Seems it was removed from the "Config" structure. Commented out the +set/get commands for it. + +x86/iVU0micro.c line 494 - too many arguments in 'vurecAnalyzeBlock' + This might be leftover code from a testrun. I removed the extra 'old' +variables. + +x86/iVU1micro.c - all "_controlfp" commands commented out. + See Interpreter.c above for details. + +Then I finally got to the Link portion of the compiler... + +Hw.o: + _aligned_malloc() is not defined in Linux. memalign() was obsoleted. +POSIX now recommends posix_memalign(boundary, size) from +for accurate boundary allocation... and working free() calls. + _aligned_free(), companion to the call above, is also not defined in +Linux. Fortunately, posix_memalign() only needs a free() call. + Both of the above was defined in Common.h + +IPU/IPU.o: + couldn't find pthread_... calls. Added -lpthread to $(LIBS) in Makefile + +FPU.o: + Certain math calls were added from . FPU2.cpp compiles those +calls... and adds a C interface to get to them. Included FPU2.o in the +object list in the Makefile. + +R5900.o: + pthread_mutex__unlock()? I thought it was just 1 underline there. Didn't +take any chances, though. Put in a define in Common.h to change it to +pthread_mutex_unlock(). + +Left to fix: + +x86/iVUmicro.o: + __assume(0): I don't know what this is used for. + +R5900.o: + InterlockedAnd(), InterlockedExchange(): Are these grouped mutex calls? + +VifDma.o: + SetNewMask(), g_vif1Masks(), g_vif0Masks(): + These were sliced off when I cut SSE off. Some work could bring them +back in, if they're needed for non-MMX/SSE/SSE2/SSE3 refrencing... + + +This doesn't even guarentee that once just these problems are fixed, the +compiled program will run. I only looked at compiling/linking. + +efp - Feb 16, 2006 diff --git a/Docs/pcsx2_faq.txt b/Docs/pcsx2_faq.txt new file mode 100644 index 0000000000..4b8cdb87ca --- /dev/null +++ b/Docs/pcsx2_faq.txt @@ -0,0 +1,229 @@ + + PPPP CCCC SSS X X 2222 + P P C C S S X X 2 2 + P P C S X X 2 + P P C S X X 2 + P P C S X X 2 + P P C SSS X 2 + PPPP C S X X 2 + P C S X X 2 + P C S X X 2 + P C C S S X X 2 + P CCCC SSS X X 2222222 + +**************** +*PCSX2 FAQ v0.1* +**************** + +This FAQ has been written for PCSX2 v0.6 + +FAQ Written by: CKemu & shadow +_________________________________________________________ + +Q: What is PCSX2? + +A: PCSX2 is a WIP PS2 (PlayStation 2) emulator, written by +linuzappz, shadow, florin. basara, asadr, goldfinger. PCSX2 is +constantly WIP (work in progress), and is in the early +stages of development (so don't expect much yet ;) ). + +Q: Why doesn't XYZ game work? + +A: PCSX2 is able to get many games to show 'screens'. Some of the games can reach ingame +and less more can be consider playable. Speed is too slow on many of them so 'viewable' is +a beter way to describe it :) + + +Q: Why don't these games work? + +A: PCSX2 is in the early stages of development. It can run some games (many of them without glitches) +but the speed issue prevent us of making the emu more compatible. + +Q: Where abouts do I find these demos? + +A:You can find some demos at http://pcsx2.ngemu.com or +http://ps2dev.livemedia.com.au. There are proberbly more +sites with PS2 homebrew demos. + +Q: Does PCSX2 require a 'real' PS2 BIOS. + +A: PCSX2 can use a 'real' BIOS, and is preferable to HLE +BIOS as it is more compatible. But HLE does work well +with many homebrew demos. + +Q: Why not use HLE? + +A: HLE is a difficult thing to do for a PS2. Game +developers use their own modules for each game. That +would mean we would have to HLE each module. This would +be a massive task, and not a good idea, as emulating +the real BIOS will mean compatibility with all released +games. + +Q: Where do I get a BIOS? + +A: You can dump the BIOS from your own PS2, DO NOT ask us +or anyone else for a BIOS, the BIOS is copyright of SONY +and is illegal to download, so we won't help you with +that. + +Q: I try to run a game, or the BIOS, but nothing happens! + +A: If no BIOS screen shows from attempting to run a +CD/DVD, your BIOS maybe incorrect. Go to +'config>configure', and under the BIOS menu, check that +firstly you haven't got the HLE BIOS selected, if you do +change to a 'real' BIOS. If you have a 'real' BIOS +selected and it still doesn't work, check that NO +percentage is written next to the BIOS, if it is for +instance "40%", your BIOS is to small (by 60%), or +corrupt (by 60%), you may need to redump it. Also if no +'real' BIOS is listed, check its not compressed 'eg +*.zip / *.rar' and extract it to the BIOS dir (note +sub-folders NOT supported, it must be in /BIOS/). + +If that is not the case, your BIOS isn't an actual PS2 +BIOS. To ensure that doesn't happen, dump your own ;) + +Q: I see lots of glitches with games/demos, why? + +A: Incomplete emulation of the GS, Vector Units etc, this +is a WIP emulator, and will have many bugs for some time, +until more is known about the PS2 hardware. Things +generally improve with each release, so you never know, +it may be fixed in the next release. + +Q: How can I help fix these bugs? + +A: Report these bugs to us, post at the offical PCSX2 +forums at http://www.ngemu.com. Make a post describing +the bug/glitch, perhaps with a screenshot showing it, +and details on your system setup, what plugins your +using etc. + +If you find any other bugs, with regards to the debugger, +plugins, or differences between what you see in the +emulator and a real PS2, feel free to email us. + +Q: How can I help develop for PCSX2? + +A: You can find the open-source plugins at +http://pcsx2.ngemu.com , coding a GS plugin or and SPU2 +plugin would help us greatly. Also if you have any +technical information on the PS2, please email us, +anyhelp is greatly appreciated. + +Q: Your emulator sucks!! I don't want to use it! + +A: Then don't, buy a real PS2. If you don't like it, +just don't and there is no need to tell us you don't +like it, the PCSX2 team put alot of hardwork into this +emulator, and don't care to know. + +Q: Can you give me some more 'technical' answers? + +A: A technical FAQ would be massive, and take months to +write. Instead email shadow / linuz with your questions. + +Q: When is the next release? + +A: The next release will happen when there is something +to show, internal changes, and technical changes don't +mean anything to the user, if they don't see something. +Pestering us will make no difference :P + +Q: GSsoft is s..l..o..w!! + +A: Then use one of the OpenGL plugins found at our site +http://pcsx2.ngemu.com or the GStaris plugin +( http://gstaris.ngemu.com ). + +Q: The emulator even with GStaris / GSmax is slow! Why? + +A: First of all, the PS2 is a powerfull piece of +hardware, and will require a powerfull machine to achive +NEAR correct speeds, + +Given that PCSX2 does not run any 'complex' commercial +games, it is hard to judge the system requirements that +will be eventually needed. Plugins and Emulator will get +faster as new releases are made, but you can improve +preformance by turning OFF "Enable Console Output" and +"Enable Interpreter CPU" under 'config>CPU>' in the menu. + +Q: Do I need a DVD drive? + +A: Yes, if you want to read a DVDrom you will need a DVD + drive, many PS2 games are written to CDrom, so its not +essential, unless you have a DVD based game you wish to +try. + +You can also use 'Linuz's CDVD ISO' plugin to run PS2 +games in ISO / BIN format from your HDD. Note only +NTFS Format drives (eg not FAT32) can store greater than +4GB in a single file. + +Q: I hear no sound! + +A: SPU2 Plugins are being worked on by a few coders, but +as of now the only SPU2 plugin is nullSPU, which outputs +no sound, If you are a coder, and feel you can help with +SPU2, please email us. + +Q: Where can I get help!!! + +A: You can get help from the people over at +http://www.ngemu.com or on IRC. Using an IRC client, log +onto #PCSX2 or #NGEMU (EFnet). You can politly ask for +help there (No BIOS / ROM / ISO requests, or you shall be +banned). If you cannot get help there, email the PCSX2 +team. + +_________________________________________________________ + +This FAQ was based on shadow's original FAQ, so thanks to +him. This was written to clear up some of the basic +questions you may have, and I hope it was of help. + +Written with very little sleep and too much coffee, so +please excuse the mistakes, they will be fixed shortly :D + +************ +*Thanks to:* +************ + +The PCSX2 team for making me a betatester, and providing us +with a fantastic PS2 emulator, and the opportinity for me to +work on SPU2 (highly WIP :P ) + +shadow, Linuzappz, Absolute0, [Tyranid], F|res, Roor, +Goldfinger, Florin, basara, asadr, CpUmaster, snake785, +mike9010, bositman, DWatcher, Keith, Martin64.....and many +more I am sure :D + +My lady, Lucy. Without her I would be lost. + +Coffee, where would we be without coffee :D + +********** +*Contact:* +********** + +If you think I should add something to this FAQ, or you +spotted a bug, you can contact me (CKemu) via IRC in +the #PCSX2 (EFnet) channel. + +You can contact the authors via: +http://pcsx2.ngemu.com (homepage) +http://www.pcsx2.net (homepage) +http://www.ngemu.com (offical forums) + +or on IRC: + +#PCSX2 (EFnet) + +Enjoy PCSX2!! + +Best Regards CKemu ( http://www.ckemu.com ). + +/EOF/ \ No newline at end of file diff --git a/Docs/specs.tex b/Docs/specs.tex new file mode 100644 index 0000000000..aca2581945 --- /dev/null +++ b/Docs/specs.tex @@ -0,0 +1,159 @@ +\documentclass[10pt]{article} + +\begin{document} +\section{...stuff...} +-order the plugins are started\\ +-platform dependent stuff, calling convention\\ + +\section{Generic functions} +The following three functions will be present in all the plugin libraries, + in order to be recognized as valid PS2E plugins. They will help + the emulator to find a plugin capabilities. + +\subsection{PS2EgetLibType} +\begin{quote}\texttt{unsigned int} PS2EgetLibType(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibType] returns the type of the plugin. + In fact it indicates the APIs supported by the dynamic library. + The returned value can be one of: +\begin{itemize} +\item PS2E\_LT\_GS 0x01 +\item PS2E\_LT\_PAD 0x02 +\item PS2E\_LT\_SPU2 0x04 +\item PS2E\_LT\_CDVD 0x08 +\item PS2E\_LT\_DEV9 0x10 +\end{itemize} +Currently, these are the only plugin types supported. Note that the values + can be ORed. +\end{description} + + + +\subsection{PS2EgetLibVersion2} +\begin{quote}\texttt{unsigned int} PS2EgetLibVersion2(\texttt{unsigned int} + type);\end{quote} + +\begin{description} +\item[PS2EgetLibVersion2] returns a combination of version numbers. +Parameter \emph{type} is used to select the functions set for which + the emulator requests version information. See \texttt{PS2EgetLibType} + for the values of this parameter. + +The 5 APIs and their corresponding specs have changed over time. + In order to prevent crashes and incompatibilities, a spec version have + been introduced as the highest 16 bits of the returned value. +\begin{itemize} +\item PS2E\_GS\_VERSION 0x0002 +\item PS2E\_PAD\_VERSION 0x0002 +\item PS2E\_SPU2\_VERSION 0x0002 +\item PS2E\_CDVD\_VERSION 0x0003 +\item PS2E\_DEV9\_VERSION 0x0001 +\end{itemize} +Notice that when the specs do change \texttt{and} the compatibility is broken, + this version number is increased. The emulator loading code will support + only one version for a certain library type at a time. If the internal + version and plugin API version does not match, the plugin + will not be loaded nor used. + +The low half of the returned value reflects the version of the plugin itself. + A major.minor versioning scheme is used on the two bytes like this: +\begin{verbatim} +...//code +return (PS2E_CDVD_VERSION<<16) | (0<<8) | (67); //version 0.67 +\end{verbatim} +\end{description} + + + +\subsection{PS2EgetLibName} +\begin{quote}\texttt{char*} PS2EgetLibName(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibName] returns a string that contains a short\footnote{ +less then 30 chars in one line} name. The string is stored + in the plugin and will be used to represent the plugin in a config dialog. +\end{description} + + + + + +\section{CDVD functions} +This section describes the functions that corresponds to CDVD\footnote{short for CD/DVD} +API - type PS2E\_LT\_CDVD(0x08). + These specs are for PS2E\_CDVD\_VERSION(0x0003). + +\subsection{CDVDinit} +\begin{quote}\texttt{int} CDVDinit(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDinit] does the initialization of the CDVD interface. + It is the first function called; so, it can be used to do all the + init stuff such as reading saved configuration, one-time hardware init and + preparing the internal structures, tables, etc\ldots + If an error is found the function will return -1, otherwise 0. +\end{description} + + + +\subsection{CDVDshutdown} +\begin{quote}\texttt{void} CDVDshutdown(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDshutdown] is called when the emulator is closed. Do now the freeing + operations. DO NOT FORGET TO FREE the resources used. The OS will probably + free the garbage left, but some pieces of hardware might need a + ``deinitialization'' procedure in order to work next time the emulator + is run. Imagine that the user will choose another plugin to run with + next time instead of yours, do not cause troubles. +\end{description} + + + +\subsection{CDVDopen} +\begin{quote}\texttt{int} CDVDopen(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDopen] is called when the emulation starts. + It is recommended that functions called from now on (until + \texttt{CDVDclose} is met) to spend few processing time. Avoid calling + blocking functions and if you do, the user should be notified visualy. + Report errors by return value and warrings using a log. + If an error is found the function will return -1 and the emulation stops, + otherwise 0. + +Do not report errors using message boxes while the emu runs, the GS plugin + might use a display mode that can cause troubles to windowing system + in showing your message. +\end{description} + + + +\subsection{CDVDclose} +\begin{quote}\texttt{void} CDVDclose(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDclose] is called when the emulation is stopped. Some of the + resources that you aquired with \texttt{CDVDstart} have to be released now + in order that other programs to use them. If you locked the CD/DVD tray, + unlock it so the user can change the disc. +\end{description} + + + +\subsection{CDVDreadTrack} +\begin{quote}\texttt{int} CDVDreadTrack(\texttt{unsigned int} + lsn, \texttt{int} mode);\end{quote} + +\begin{description} +\item[CDVDreadTrack] is the function that performs the read of \texttt{a} + sector from the CD/DVD. Parameter \emph{lsn} specifies the absolute value + of the sector number in linear addressing mode without \emph{lead-in}\footnote{i.e.\ +without leading 150 sectors == 2 seconds}. Usualy, the plugin will read + a full sector of 2352 bytes in its internal buffer. + The second parameter tells what port of ... +\end{description} + +\end{document} + diff --git a/Docs/threads.txt b/Docs/threads.txt new file mode 100644 index 0000000000..1da83588a0 --- /dev/null +++ b/Docs/threads.txt @@ -0,0 +1,34 @@ + OK -> done & tested +---- -> not applicable +xxxx -> dummy +32³CreateThread º OK ³----³ +33³DeleteThread º----³ ³ +34³StartThread º----³ OK ³ +35³ExitThread º----³ ³ +36³ExitDeleteThread º----³ ³ +37³TerminateThread º----³ ³ +38³iTerminateThread º ³ ³ +39³DisableDispatchThread ºxxxx³xxxx³ +40³EnableDispatchThread ºxxxx³xxxx³ +41³ChangeThreadPriority º----³ OK ³ +42³iChangeThreadPriority º OK ³----³ +43³RotateThreadReadyQueue º----³ ³ +44³iRotateThreadReadyQueue º ³ ³ +45³ReleaseWaitThread º----³ ³ +46³iReleaseWaitThread º ³ ³ +47³GetThreadId º OK ³----³ +48³ReferThreadStatus ÍÍ» º OK ³----³ +49³iReferThreadStatus Íͼ º OK ³----³ +50³SleepThread º----³ ³ +51³WakeupThread º----³ ³ +52³iWakeupThread º ³ ³ +53³CancelWakeupThread ÍÍ» ºdone³----³ +54³iCancelWakeupThread Íͼ ºdone³----³ +55³SuspendThread ÍÍ» º ³ ³ +56³iSuspendThread Íͼ º ³ ³ +57³ResumeThread º----³ ³ +58³iResumeThread º ³ ³ +59³JoinThread ºxxxx³xxxx³ +60³RFU060_InitializeMainThreadº OK ³----³ +61³RFU061_InitializeHeapArea º OK ³----³ +62³EndOfHeap º OK ³----³ \ No newline at end of file diff --git a/EEregs.h b/EEregs.h new file mode 100644 index 0000000000..a25b709e16 --- /dev/null +++ b/EEregs.h @@ -0,0 +1,40 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EEREGS_H__ +#define __EEREGS_H__ + +#define at cpuRegs.GPR.n.at +#define k0 cpuRegs.GPR.n.k0 +#define k1 cpuRegs.GPR.n.k1 +#define v0 cpuRegs.GPR.n.v0 +#define v1 cpuRegs.GPR.n.v1 +#define a0 cpuRegs.GPR.n.a0 +#define a1 cpuRegs.GPR.n.a1 +#define a2 cpuRegs.GPR.n.a2 +#define a3 cpuRegs.GPR.n.a3 +#define t0 cpuRegs.GPR.n.t0 +#define s0 cpuRegs.GPR.n.s0 +#define gp cpuRegs.GPR.n.gp +#define fp cpuRegs.GPR.n.s8 +#define sp cpuRegs.GPR.n.sp +#define ra cpuRegs.GPR.n.ra + +#define pc0 cpuRegs.pc + +#endif /* __EEREGS_H__ */ diff --git a/Elfheader.c b/Elfheader.c new file mode 100644 index 0000000000..35c74b9964 --- /dev/null +++ b/Elfheader.c @@ -0,0 +1,631 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include //2002-09-28 (Florin) +#include + +#include "Common.h" +#include "CDVDisodrv.h" + +typedef struct { + u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) + u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE + u16 e_machine; //Processor: 8=MIPS R3000 + u32 e_version; //Version: 1=current + u32 e_entry; //Entry point address + u32 e_phoff; //Start of program headers (offset from file start) + u32 e_shoff; //Start of section headers (offset from file start) + u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips + u16 e_ehsize; //ELF header size (0x34 = 52 bytes) + u16 e_phentsize; //Program headers entry size + u16 e_phnum; //Number of program headers + u16 e_shentsize; //Section headers entry size + u16 e_shnum; //Number of section headers + u16 e_shstrndx; //Section header stringtable index +} ELF_HEADER; + +typedef struct { + u32 p_type; //see notes1 + u32 p_offset; //Offset from file start to program segment. + u32 p_vaddr; //Virtual address of the segment + u32 p_paddr; //Physical address of the segment + u32 p_filesz; //Number of bytes in the file image of the segment + u32 p_memsz; //Number of bytes in the memory image of the segment + u32 p_flags; //Flags for segment + u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment +} ELF_PHR; + +/* +notes1 +------ +0=Inactive +1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 +2=Dynamic linking +3=Interpreter. The array element must specify a path name +4=Note. The array element must specify the location and size of aux. info +5=reserved +6=The array element must specify location and size of the program header table. +*/ + +typedef struct { + u32 sh_name; //No. to the index of the Section header stringtable index + u32 sh_type; //See notes2 + u32 sh_flags; //see notes3 + u32 sh_addr; //Section start address + u32 sh_offset; //Offset from start of file to section + u32 sh_size; //Size of section + u32 sh_link; //Section header table index link + u32 sh_info; //Info + u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. + u32 sh_entsize; //Fixed size entries. +} ELF_SHR; +/* +notes 2 +------- +Type: +0=Inactive +1=PROGBITS +2=SYMTAB symbol table +3=STRTAB string table +4=RELA relocation entries +5=HASH hash table +6=DYNAMIC dynamic linking information +7=NOTE +8=NOBITS +9=REL relocation entries +10=SHLIB +0x70000000=LOPROC processor specifc +0x7fffffff=HIPROC +0x80000000=LOUSER lower bound +0xffffffff=HIUSER upper bound + +notes 3 +------- +Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) +1=Write section contains data the is be writeable during execution. +2=Alloc section occupies memory during execution +4=Exec section contains executable instructions +0xf0000000=Mask bits processor-specific +*/ + +typedef struct { + u32 st_name; + u32 st_value; + u32 st_size; + u8 st_info; + u8 st_other; + u16 st_shndx; +} Elf32_Sym; + +#define ELF32_ST_TYPE(i) ((i)&0xf) + +typedef struct { + u32 r_offset; + u32 r_info; +} Elf32_Rel; + +//unfinished!!!! + +char *sections_names; + +ELF_HEADER *elfHeader; +ELF_PHR *elfProgH; +ELF_SHR *elfSectH; +char *name; +u8 *elfdata; +u32 elfsize; + +struct stat sbuf; +struct TocEntry toc; + +//2002-09-19 (Florin) +char args[256]="ez.m2v"; //to be accessed by other files +unsigned int args_ptr; //a big value; in fact, it is an address + +//in a0 is passed the address of the command line args, +//i.e. a pointer to an area like this: +//+00 unknown/unused +//+04 argc; number of arguments +//+08 argv[0]; address of the first parameter - program name (char*) - +//+08 argv[1]; address of the second parameter (char*) | +//+0C argv[2]; and so on | +//........ | +//+08+4*argc the program name(first param) <-- +//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args' +// see above 'char args[256];' +unsigned int parseCommandLine( char *filename ) +{ + if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) ) + { // 4 + 4 + 256 + char * p; + int argc, + i; + + args_ptr -= 256; + if ( args_ptr < 0 ) + { + return 0; + } + args[ 255 ] = 0; + memcpy( &PS2MEM_BASE[ args_ptr ], args, 256 ); //params 1, 2, etc copied + memset( &PS2MEM_BASE[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) ); +#ifdef __WIN32__ + p = strrchr( filename, '\\' ); +#else //linux + p = strrchr( filename, '/' ); +#endif + if ( p ) + { + p++; + } + else + { + p = filename; + } + args_ptr -= strlen( p ) + 1; + if ( args_ptr < 0 ) + { + return 0; + } + strcpy( &PS2MEM_BASE[ args_ptr ], p ); //fill param 0; i.e. name of the program + + for ( i = strlen( p ) + 1 + 256, argc = 0; i > 0; i-- ) + { + while ( i && ( ( PS2MEM_BASE[ args_ptr + i ] == 0 ) || ( PS2MEM_BASE[ args_ptr + i ] == 32 ) ) ) + { + i--; + } + if ( PS2MEM_BASE[ args_ptr + i + 1 ] == ' ' ) + { + PS2MEM_BASE[ args_ptr + i + 1 ] = 0; + } + while ( i && ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i] != 32 ) ) + { + i--; + } + if ( ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i ] != 32 ) ) + { //i==0 + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i; + } + else + { + if ( ( PS2MEM_BASE[ args_ptr + i + 1 ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i + 1 ] != 32 ) ) + { + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i + 1; + } + } + } + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 1 ] = argc; //how many args + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all + + return ( args_ptr - argc * 4 - 8 ); + } + + return 0; +} +//--------------- + +int readFile( char *Exepath, char *ptr, u32 offset, int size ) { + FILE *f; + int fi; + + if ((strnicmp( Exepath, "cdrom0:", strlen("cdrom0:")) == 0) || + (strnicmp( Exepath, "cdrom1:", strlen("cdrom0:")) == 0)) { + if ((u32)offset >= toc.fileSize) return -1; + fi = CDVDFS_open(Exepath + strlen("cdromN:"), 1);//RDONLY + if (fi < 0) return -1; + CDVDFS_lseek(fi, offset, SEEK_SET); + size = CDVDFS_read(fi, ptr, size); + CDVDFS_close(fi ); + } else { + f = fopen(Exepath, "rb"); + if (f == NULL) return -1; + if ( offset >= (u64)sbuf.st_size) return -1; + fseek(f, offset, SEEK_SET); + size = fread(ptr, 1, size, f); + fclose(f); + } + + return size; +} + +int loadHeaders( char *Exepath ) { + elfHeader = (ELF_HEADER*)elfdata; + + if ( ( elfHeader->e_shentsize != sizeof(ELF_SHR) ) && ( elfHeader->e_shnum > 0 ) ) { + SysMessage( "size of section header not standard\n" ); + } + + if((elfHeader->e_shnum * elfHeader->e_shentsize) != 0) { + elfSectH = (ELF_SHR *) malloc( elfHeader->e_shnum * elfHeader->e_shentsize ); + } else { + elfSectH = NULL; + } + + if ( ( elfHeader->e_phnum * elfHeader->e_phentsize ) != 0 ) { + elfProgH = (ELF_PHR *) malloc( elfHeader->e_phnum * elfHeader->e_phentsize ); + } else { + elfProgH = NULL; + } + +#ifdef ELF_LOG + ELF_LOG( "type: " ); +#endif + switch( elfHeader->e_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", elfHeader->e_type ); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG( "no file type" ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG( "relocatable" ); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG( "executable" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG( "\n" ); + ELF_LOG( "machine: " ); +#endif + switch ( elfHeader->e_machine ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown" ); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG( "mips_rs3000" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("version: %d\n",elfHeader->e_version); + ELF_LOG("entry: %08x\n",elfHeader->e_entry); + ELF_LOG("flags: %08x\n",elfHeader->e_flags); + ELF_LOG("eh size: %08x\n",elfHeader->e_ehsize); + ELF_LOG("ph off: %08x\n",elfHeader->e_phoff); + ELF_LOG("ph entsiz: %08x\n",elfHeader->e_phentsize); + ELF_LOG("ph num: %08x\n",elfHeader->e_phnum); + ELF_LOG("sh off: %08x\n",elfHeader->e_shoff); + ELF_LOG("sh entsiz: %08x\n",elfHeader->e_shentsize); + ELF_LOG("sh num: %08x\n",elfHeader->e_shnum); + ELF_LOG("sh strndx: %08x\n",elfHeader->e_shstrndx); + + ELF_LOG("\n"); +#endif + + return TRUE; +} + + +BOOL loadProgramHeaders( char *Exepath ) +{ + int i; + + if ( elfHeader->e_phnum == 0 ) + { + return TRUE; + } + + // is this critical, or warning? + if ( elfHeader->e_phentsize != sizeof( ELF_PHR ) ) + { + SysMessage( "size of program header not standard\n" ); + } + + elfProgH = (ELF_PHR*)&elfdata[elfHeader->e_phoff]; + + for ( i = 0 ; i < elfHeader->e_phnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Program Header\n" ); + ELF_LOG( "type: " ); +#endif + switch ( elfProgH[ i ].p_type ) { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", (int)elfProgH[ i ].p_type ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("load"); +#endif + if (elfProgH[ i ].p_offset < elfsize) { + int size; + + if ((elfProgH[ i ].p_filesz + elfProgH[ i ].p_offset) > elfsize) { + size = elfsize - elfProgH[ i ].p_offset; + } else { + size = elfProgH[ i ].p_filesz; + } + memcpy(&PS2MEM_BASE[elfProgH[ i ].p_paddr & 0x1ffffff], + &elfdata[elfProgH[ i ].p_offset], + size); +#ifdef ELF_LOG + ELF_LOG("\t*LOADED*"); +#endif + } + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset); + ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr); + ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr); + ELF_LOG("file size: %08x\n",elfProgH[i].p_filesz); + ELF_LOG("mem size: %08x\n",elfProgH[i].p_memsz); + ELF_LOG("flags: %08x\n",elfProgH[i].p_flags); + ELF_LOG("palign: %08x\n",elfProgH[i].p_align); + ELF_LOG("\n"); +#endif + } + + return TRUE; +} + + +BOOL loadSectionHeaders( char * Exepath ) +{ + int i; + int i_st = -1; + int i_dt = -1; + + if (elfHeader->e_shnum == 0 || + elfHeader->e_shoff > elfsize) { + return TRUE; + } + + elfSectH = (ELF_SHR*)&elfdata[elfHeader->e_shoff]; + + if ( elfHeader->e_shstrndx < elfHeader->e_shnum ) { + sections_names = (char *)&elfdata[elfSectH[ elfHeader->e_shstrndx ].sh_offset]; + } + + for ( i = 0 ; i < elfHeader->e_shnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Section Header [%x] %s", i, §ions_names[ elfSectH[ i ].sh_name ] ); +#endif + if ( elfSectH[i].sh_flags & 0x2 ) { + //2002-09-19 (Florin) + args_ptr = min( args_ptr, elfSectH[ i ].sh_addr & 0x1ffffff ); + //--------------- +/* if (elfSectH[i].sh_offset < elfsize) { + int size; + + if ((elfSectH[i].sh_size + elfSectH[i].sh_offset) > elfsize) { + size = elfsize - elfSectH[i].sh_offset; + } else { + size = elfSectH[i].sh_size; + } + memcpy(&PS2MEM_BASE[ elfSectH[ i ].sh_addr &0x1ffffff ], + &elfdata[elfSectH[i].sh_offset], + size); + } +#ifdef ELF_LOG + ELF_LOG( "\t*LOADED*" ); +#endif*/ + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("type: "); +#endif + switch ( elfSectH[ i ].sh_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG("unknown %08x",elfSectH[i].sh_type); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG("null"); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("progbits"); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG("symtab"); +#endif + break; + + case 0x3: +#ifdef ELF_LOG + ELF_LOG("strtab"); +#endif + break; + + case 0x4: +#ifdef ELF_LOG + ELF_LOG("rela"); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG("no bits"); +#endif + break; + + case 0x9: +#ifdef ELF_LOG + ELF_LOG("rel"); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("flags: %08x\n", elfSectH[i].sh_flags); + ELF_LOG("addr: %08x\n", elfSectH[i].sh_addr); + ELF_LOG("offset: %08x\n", elfSectH[i].sh_offset); + ELF_LOG("size: %08x\n", elfSectH[i].sh_size); + ELF_LOG("link: %08x\n", elfSectH[i].sh_link); + ELF_LOG("info: %08x\n", elfSectH[i].sh_info); + ELF_LOG("addralign: %08x\n", elfSectH[i].sh_addralign); + ELF_LOG("entsize: %08x\n", elfSectH[i].sh_entsize); +#endif + // dump symbol table + + if ( elfSectH[ i ].sh_type == 0x02 ) + { + i_st = i; + i_dt = elfSectH[i].sh_link; + } + } + + if ( ( i_st >= 0 ) && ( i_dt >= 0 ) ) + { + char * SymNames; + Elf32_Sym * eS; + + SymNames = (char*)&elfdata[elfSectH[ i_dt ].sh_offset]; + eS = (Elf32_Sym*)&elfdata[elfSectH[ i_st ].sh_offset]; + SysPrintf("found %d symbols\n", elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym )); + + for ( i = 1; i < (int)( elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym ) ); i++ ) { + if ( ( eS[ i ].st_value != 0 ) && ( ELF32_ST_TYPE( eS[ i ].st_info ) == 2 ) ) { +// SysPrintf("%x:%s\n", eS[i].st_value, &SymNames[eS[i].st_name]); + disR5900AddSym( eS[i].st_value, &SymNames[ eS[ i ].st_name ] ); +/* if (!strcmp(&SymNames[eS[i].st_name], "sceSifCheckStatRpc")) { + psMu32(eS[i].st_value & 0x1ffffff) = (0x3b << 26) | 1; + SysPrintf("found sceSifCheckStatRpc!!\n"); + }*/ + } + } + } + + return TRUE; +} + + +int loadElfFile(char *filename) { + char str[256]; + char str2[256]; + u32 crc; + u32 i; + + SysPrintf("loadElfFile: %s\n", filename); + if (strnicmp( filename, "cdrom0:", strlen( "cdrom0:" ) ) && + strnicmp( filename, "cdrom1:", strlen( "cdrom1:" ) ) ) { + if ( stat( filename, &sbuf ) != 0 ) + return -1; + elfsize = sbuf.st_size; + } else { + CDVDFS_init( ); + if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 ) + return -1; + elfsize = toc.fileSize; + } + + SysPrintf("loadElfFile: %d\n", elfsize); + elfdata = (u8*)malloc(elfsize); + if (elfdata == NULL) return -1; + readFile(filename, elfdata, 0, elfsize); + +/* { + FILE *f = fopen("game.elf", "wb"); + fwrite(elfdata, 1, elfsize, f); + fclose(f); + }*/ + + //2002-09-19 (Florin) + args_ptr = 0xFFFFFFFF; //big value, searching for minimum + //------------------- + loadHeaders( filename ); + cpuRegs.pc = elfHeader->e_entry; //set pc to proper place + loadProgramHeaders( filename ); + loadSectionHeaders( filename ); + +#ifdef ELF_LOG + ELF_LOG( "PC set to: %8.8lx\n", cpuRegs.pc ); +#endif + cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; + cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok + + //2002-09-19 (Florin) + cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); + //--------------- + + for ( i = 0; i < 0x100000; i++ ) { + if ( strcmp( "rom0:OSDSYS", PSM( i ) ) == 0 ) { + strcpy( PSM( i ), filename ); + SysPrintf( "addr %x \"%s\" -> \"%s\"\n", i, "rom0:OSDSYS", filename ); + } + } + + //CRC + for (i=0, crc=0; i +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +// Helper Macros +//**************************************************************** +#define _Ft_ ( ( cpuRegs.code >> 16 ) & 0x1F ) +#define _Fs_ ( ( cpuRegs.code >> 11 ) & 0x1F ) +#define _Fd_ ( ( cpuRegs.code >> 6 ) & 0x1F ) + +#define _FtValf_ fpuRegs.fpr[ _Ft_ ].f +#define _FsValf_ fpuRegs.fpr[ _Fs_ ].f +#define _FdValf_ fpuRegs.fpr[ _Fd_ ].f +#define _FAValf_ fpuRegs.ACC.f + +#define _ContVal_ fpuRegs.fprc[ 31 ] + +// Testing +#define _FtValUl_ fpuRegs.fpr[ _Ft_ ].UL +#define _FsValUl_ fpuRegs.fpr[ _Fs_ ].UL +#define _FdValUl_ fpuRegs.fpr[ _Fd_ ].UL +#define _FAValUl_ fpuRegs.ACC.UL + +//**************************************************************** + +void COP1() { +#ifdef FPU_LOG + FPU_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP1PrintTable[_Rs_](); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + + + +void LWC1() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);// ((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memRead32(addr, &fpuRegs.fpr[_Rt_].UL); +} + +void SWC1() { + s32 addr; + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);//((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memWrite32(addr, fpuRegs.fpr[_Rt_].UL); +} + +void COP1_BC1() { + Int_COP1BC1PrintTable[_Rt_](); +} + +void COP1_S() { + Int_COP1SPrintTable[_Funct_](); +} + +void COP1_W() { + Int_COP1WPrintTable[_Funct_](); +} + +void COP1_Unknown() { +#ifdef FPU_LOG + FPU_LOG("Unknown FPU opcode called\n"); +#endif +} + + + +void MFC1() { + if ( !_Rt_ ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)_FsValUl_; +} + +void CFC1() { + if ( !_Rt_ || ( _Fs_ != 0 && _Fs_ != 31 ) ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)fpuRegs.fprc[_Fs_]; +} + +void MTC1() { + _FsValUl_ = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +void CTC1() { + if(_Fs_!=31) return; + fpuRegs.fprc[_Fs_] = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +#define C_cond_S(cond) \ + _ContVal_ = ( _FsValf_ cond _FtValf_ ) ? \ + ( _ContVal_ | 0x00800000 ) : \ + ( _ContVal_ & ~0x00800000 ); + +void C_F() { _ContVal_ &= ~0x00800000;} //clears C regardless +void C_EQ() { C_cond_S(==); } +void C_LT() { C_cond_S(<); } +void C_LE() { C_cond_S(<=); } + +#define BC1(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } +void BC1F() { BC1(==); } +void BC1T() { BC1(!=); } + +#define BC1L(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } else cpuRegs.pc += 4; +void BC1FL() { BC1L(==); } // Equal to 0 +void BC1TL() { BC1L(!=); } // different from 0 + + +void ADD_S() { _FdValf_ = _FsValf_ + _FtValf_; } +void SUB_S() { _FdValf_ = _FsValf_ - _FtValf_; } +void MUL_S() { _FdValf_ = _FsValf_ * _FtValf_; } +void MOV_S() { _FdValf_ = _FsValf_; } +void NEG_S() { _FdValf_ = -_FsValf_; } +void ADDA_S() { _FAValf_ = _FsValf_ + _FtValf_; } +void SUBA_S() { _FAValf_ = _FsValf_ - _FtValf_; } +void MULA_S() { _FAValf_ = _FsValf_ * _FtValf_; } +void MADD_S() { _FdValf_ = _FAValf_ + ( _FsValf_ * _FtValf_ ); } +void MSUB_S() { _FdValf_ = _FAValf_ - ( _FsValf_ * _FtValf_ ); } +void MADDA_S() { _FAValf_ += _FsValf_ * _FtValf_; } +void MSUBA_S() { _FAValf_ -= _FsValf_ * _FtValf_; } +void ABS_S() { _FdValf_ = fpufabsf(_FsValf_); } +void MAX_S() { _FdValf_ = max( _FsValf_, _FtValf_ ); } +void MIN_S() { _FdValf_ = min( _FsValf_, _FtValf_ ); } +void DIV_S() { if ( _FtValf_ ) { _FdValf_ = _FsValf_ / _FtValf_; } } +void SQRT_S() { + //if ( _FtValf_ >= 0.0f ) { _FdValf_ = fpusqrtf( _FtValf_ ); } + //else { + _FdValf_ = fpusqrtf(fpufabsf(_FtValf_)); + //} +} +void CVT_S() { _FdValf_ = (float)(s32)_FsValUl_; } +void CVT_W() { + if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValUl_ = (s32)(float)_FsValf_; } + else if ( _FsValUl_ & 0x80000000 ) { _FdValUl_ = 0x80000000; } + else { _FdValUl_ = 0x7fffffff; } +} + +void RSQRT_S() { + if ( _FtValf_ >= 0.0f ) { + float tmp = fpusqrtf( _FtValf_ ); + if ( tmp != 0 ) { _FdValf_ = _FsValf_ / tmp; } + } +} + +//3322 2222 2222 1111 1111 1100 0000 0000 +//1098 7654 3210 9876 5432 1098 7654 3210 +//0000 0000 0000 0000 0000 0000 0000 0000 diff --git a/FPU2.cpp b/FPU2.cpp new file mode 100644 index 0000000000..a7f397498a --- /dev/null +++ b/FPU2.cpp @@ -0,0 +1,25 @@ +#include + +// sqrtf only defined in C++ +extern "C" { + +float (*fpusqrtf)(float fval) = 0; +float (*fpufabsf)(float fval) = 0; +float (*fpusinf)(float fval) = 0; +float (*fpucosf)(float fval) = 0; +float (*fpuexpf)(float fval) = 0; +float (*fpuatanf)(float fval) = 0; +float (*fpuatan2f)(float fvalx, float fvaly) = 0; + +void InitFPUOps() +{ + fpusqrtf = sqrtf; + fpufabsf = fabsf; + fpusinf = sinf; + fpucosf = cosf; + fpuexpf = expf; + fpuatanf = atanf; + fpuatan2f = atan2f; +} + +} \ No newline at end of file diff --git a/FiFo.c b/FiFo.c new file mode 100644 index 0000000000..8dc218f34c --- /dev/null +++ b/FiFo.c @@ -0,0 +1,181 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//well that might need a recheck :P +//(shadow bug0r work :P) + +//plz, change this file according to FIFO defs in hw.h +/* u64 VIF0[0x1000]; + u64 VIF1[0x1000]; + u64 GIF[0x1000]; + u64 IPU_out_FIFO[0x160]; // 128bit + u64 IPU_in_FIFO[0x160]; // 128bit +*/ + +#include +#include +#include + +#include "Common.h" +#include "Hw.h" + +#include + +////////////////////////////////////////////////////////////////////////// +/////////////////////////// Quick & dirty FIFO :D //////////////////////// +////////////////////////////////////////////////////////////////////////// +extern int fifo_wwrite(u32* pMem, int size); +extern void fifo_wread1(void *value); + +extern int g_nIPU0Data; +extern u8* g_pIPU0Pointer; + +// NOTE: cannot use XMM/MMX regs +void ReadFIFO(u32 mem, u64 *out) { + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("ReadFIFO VIF0 0x%08X\n", mem); +#endif + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else + if ((mem >= 0x10005000) && (mem < 0x10006000)) { + +#ifdef PCSX_DEVBUILD + VIF_LOG("ReadFIFO VIF1 0x%08X\n", mem); + + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("reading from vif1 fifo when stalled\n"); + } +#endif + + if (vif1Regs->stat & 0x800000) { + if (--psHu32(D1_QWC) == 0) { + vif1Regs->stat&= ~0x1f000000; + } else { + } + } + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else if( (mem&0xfffff010) == 0x10007000) { + + if( g_nIPU0Data > 0 ) { + out[0] = *(u64*)(g_pIPU0Pointer); + out[1] = *(u64*)(g_pIPU0Pointer+8); + g_nIPU0Data--; + g_pIPU0Pointer += 16; + } + return; + }else if ( (mem&0xfffff010) == 0x10007010) { + fifo_wread1((void*)out); + return; + } + SysPrintf("ReadFIFO Unknown %x\n", mem); +} + +void ConstReadFIFO(u32 mem) +{ + // not done +} + +extern HANDLE g_hGsEvent; + +void WriteFIFO(u32 mem, u64 *value) { + int ret; + + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF0 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + ret = VIF0transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10005000) && (mem < 0x10006000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF1 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + if(vif1Regs->stat & VIF1_STAT_FDR) + SysPrintf("writing to fifo when fdr is set!\n"); + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("writing to vif1 fifo when stalled\n"); + } +#endif + ret = VIF1transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10006000) && (mem < 0x10007000)) { + u64* data; +#ifdef GIF_LOG + GIF_LOG("WriteFIFO GIF 0x%08X\n", mem); +#endif + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + + if( CHECK_MULTIGS ) { + data = (u64*)GSRingBufCopy(NULL, 16, GS_RINGTYPE_P3); + + data[0] = value[0]; + data[1] = value[1]; + GSgifTransferDummy(2, (u32*)data, 1); + GSRINGBUF_DONECOPY(data, 16); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); + } + else { + FreezeXMMRegs(1); +#ifdef GSCAPTURE + extern u32 g_loggs, g_gstransnum, g_gsfinalnum; + + if( !g_loggs || (g_loggs && g_gstransnum++ < g_gsfinalnum)) { + GSgifTransfer3((u32*)value, 1-GSgifTransferDummy(2, (u32*)value, 1)); + } +#else + GSgifTransfer3((u32*)value, 1); +#endif + FreezeXMMRegs(0); + } + + } else + if ((mem&0xfffff010) == 0x10007010) { +#ifdef IPU_LOG + IPU_LOG("WriteFIFO IPU_in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X\n", (mem - 0x10007010)/8, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + //commiting every 16 bytes + while( fifo_wwrite((void*)value, 1) == 0 ) { + SysPrintf("IPU sleeping\n"); + Sleep(1); + } + } else { + SysPrintf("WriteFIFO Unknown %x\n", mem); + } +} + +void ConstWriteFIFO(u32 mem) { +} \ No newline at end of file diff --git a/GS.c b/GS.c new file mode 100644 index 0000000000..27c6049b1e --- /dev/null +++ b/GS.c @@ -0,0 +1,1707 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// rewritten by zerofrog to add multithreading/gs caching to GS and VU1 + +#include "Common.h" + +#include + +#include +#include "ir5900.h" +#include "VUmicro.h" + +#ifdef WIN32_VIRTUAL_MEM +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) +#else +#define gif ((DMACh*)&psH[0xA000]) +#endif + +#define ENABLE_GS_CACHING_SIZE 0x4000 // min size +//#define _RINGBUF_DEBUG + +#ifdef WIN32_VIRTUAL_MEM +#define PS2GS_BASE(mem) ((PS2MEM_BASE+0x12000000)+(mem&0x13ff)) +#else +u8 g_RealGSMem[0x2000]; +#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff)) +#endif + +#ifdef GSCAPTURE +u32 g_loggs = 0; +u32 g_gstransnum = 0; +u32 g_gslimit = 0; +u32 g_gsfinalnum = 0; +#endif + +// dummy GS for processing SIGNAL, FINISH, and LABEL commands +typedef struct +{ + u32 nloop : 15; + u32 eop : 1; + u32 dummy0 : 16; + u32 dummy1 : 14; + u32 pre : 1; + u32 prim : 11; + u32 flg : 2; + u32 nreg : 4; + u32 regs[2]; + u32 curreg; +} GIFTAG; + +static GIFTAG g_path[3]; +__declspec(align(16)) static BYTE s_byRegs[3][16]; + +// could convert to pthreads easily, just don't have the time +HANDLE g_hGsEvent = NULL, // set when path3 is ready to be processed + g_hVuGSExit = NULL; // set when thread needs to exit +HANDLE g_hGSOpen = NULL, g_hGSDone = NULL; +HANDLE g_hVuGSThread = NULL; +u32 CSRw; + +HANDLE g_hAllGsReady[3] = {NULL}; + +DWORD WINAPI VuGSThreadProc(LPVOID lpParam); + +// g_pGSRingPos == g_pGSWritePos => fifo is empty +u8* g_pGSRingPos = NULL, // cur pos ring is at + *g_pGSWritePos = NULL; // cur pos ee thread is at +u8 *g_pGSTempWritePos = NULL, *g_pGSTempReadPos = NULL; // cur pos ee thread is at + +extern int g_nCounters[]; + +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +CRITICAL_SECTION g_PageAddrSection; +u32 *g_pGSCurFreePages = NULL, *g_pGSWriteFreePages = NULL; + +void gsInit() +{ + if( VirtualAlloc(GS_PAGEADDRS, GSPAGES_STRIDE*(0x10000000>>GS_SHIFT), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE) != GS_PAGEADDRS ) { + MessageBox(NULL, "Cannot alloc GS page buffer\n", "Error", MB_OK); + exit(0); + } + memset(GS_PAGEADDRS, 0, GSPAGES_STRIDE*(0x02000000>>GS_SHIFT)); + + if( CHECK_MULTIGS ) { + g_hGsEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + g_hVuGSExit = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSOpen = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSDone = CreateEvent(NULL, FALSE, FALSE, NULL); + + SysPrintf("gsInit\n"); + + g_pGSRingPos = VirtualAlloc(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if( g_pGSRingPos != GS_RINGBUFFERBASE ) { + MessageBox(NULL, "Cannot alloc GS ring buffer\n", "Error", MB_OK); + exit(0); + } + + g_pGSTempReadPos = g_pGSTempWritePos = VirtualAlloc(GS_RINGTEMPBASE, GS_RINGTEMPSIZE, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if( g_pGSTempWritePos != GS_RINGTEMPBASE ) { + MessageBox(NULL, "Cannot alloc GS RingTemp buffer\n", "Error", MB_OK); + exit(0); + } + + InitializeCriticalSection(&g_PageAddrSection); + + InterlockedExchangePointer(&g_pGSWritePos, GS_RINGBUFFERBASE); + g_hVuGSThread = CreateThread(NULL, 0, VuGSThreadProc, NULL, 0, NULL); + } +} + +void gsWaitGS() +{ + while( g_pGSRingPos != g_pGSWritePos ) + Sleep(1); +} + +void gsShutdown() +{ + VirtualFree(GS_PAGEADDRS, GSPAGES_STRIDE*(0x02000000>>GS_SHIFT), MEM_DECOMMIT|MEM_RELEASE); + + if( CHECK_MULTIGS ) { + + SetEvent(g_hVuGSExit); + SysPrintf("Closing gs thread\n"); + WaitForSingleObject(g_hVuGSThread, INFINITE); + CloseHandle(g_hVuGSThread); + CloseHandle(g_hGsEvent); + CloseHandle(g_hVuGSExit); + CloseHandle(g_hGSOpen); + CloseHandle(g_hGSDone); + + g_pGSWriteFreePages = g_pGSCurFreePages = NULL; + g_pGSTempReadPos = NULL; + + DeleteCriticalSection(&g_PageAddrSection); + + VirtualFree(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_DECOMMIT|MEM_RELEASE); + VirtualFree(GS_RINGTEMPBASE, GS_RINGTEMPSIZE, MEM_DECOMMIT|MEM_RELEASE); + } + else GSclose(); +} + +static void GSRingTempReserve(u32 size) +{ + u8* writepos = g_pGSTempWritePos; + assert( size <= GS_RINGTEMPSIZE ); + + // there always has to be memory + if( g_pGSTempWritePos + size > GS_RINGTEMPEND ) { + if( writepos < g_pGSTempReadPos ) { + do { + SetEvent(g_hGsEvent); + Sleep(1); + } while( writepos < g_pGSTempReadPos ); + } + + // notify GS + writepos = GS_RINGTEMPBASE; + } + + if( writepos < g_pGSTempReadPos && writepos+size >= g_pGSTempReadPos ) { + do { + SetEvent(g_hGsEvent); + Sleep(1); + } while( writepos < g_pGSTempReadPos && writepos+size >= g_pGSTempReadPos ); + } + + g_pGSTempWritePos = writepos; +} + +static u8* GSRingTempCopy(u32 size) +{ + u8* writepos; + assert( size <= GS_RINGTEMPSIZE ); + //GSRingTempReserve(size); + + writepos = g_pGSTempWritePos; + g_pGSTempWritePos += size; + assert( g_pGSTempWritePos <= GS_RINGTEMPEND ); + + //SysPrintf("writepos copy: %x %d\n", writepos, size); + return writepos; +} + +typedef u8* PU8; + +u8* GSRingBufCopy(void* mem, u32 size, u32 type) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + assert( size < 0x10000*16 ); + assert( writepos < GS_RINGBUFFEREND ); + assert( ((u32)writepos & 15) == 0 ); + assert( (size&15) == 0); + + size += 16; + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos + size > GS_RINGBUFFEREND ) { + + // skip to beginning + while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) { + SetEvent(g_hGsEvent); + Sleep(1); + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } + + // notify GS + if( writepos != GS_RINGBUFFEREND ) { + *(u32*)writepos = GS_RINGTYPE_RESTART; + } + + writepos = GS_RINGBUFFERBASE; + } + + while( writepos < tempbuf && (writepos+size >= g_pGSRingPos || (writepos+size == GS_RINGBUFFEREND && g_pGSRingPos == GS_RINGBUFFERBASE)) ) { + SetEvent(g_hGsEvent); + Sleep(1); + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } + +#ifdef WIN32_VIRTUAL_MEM + if( ENABLE_GS_CACHING && size >= ENABLE_GS_CACHING_SIZE && mem != NULL && (u8*)mem < PS2MEM_BASE+0x10000000 ) { + u32 val; + u32 i; + u32* page = GS_PAGEADDRS+(((u32)((u8*)mem-PS2MEM_BASE)&0x01ffffff)>>GS_SHIFT)*(GSPAGES_MEMADDRS+1); + u32 numpages = (((u32)mem+size-1)>>GS_SHIFT) - ((u32)mem>>GS_SHIFT)+1; + + // inc all pages + for(i = 0; i < numpages; ++i) { + if( (u8)page[0] >= GSPAGES_MEMADDRS ) + break; + + val = InterlockedExchangeAdd(page, 0x40000001); + + assert( (u8)val < GSPAGES_MEMADDRS ); + + // upper 2 bits are index + page[(val>>30)+1] = (u32)writepos; + page += GSPAGES_MEMADDRS+1; + } + + if( i == numpages ) { + // succeeded, so fill necessary data + *(u32*)writepos = GS_RINGTYPE_MEMREF|type|(((size-16)>>4)<<16); + *(u32*)(writepos+4) = (u32)mem; + *(u32*)(writepos+8) = (u32)(page-(GSPAGES_MEMADDRS+1)*numpages); + *(u32*)(writepos+12) = (u32)numpages; + + writepos += 16; + +#ifndef _RINGBUF_DEBUG + if( writepos == GS_RINGBUFFEREND ) writepos = GS_RINGBUFFERBASE; + InterlockedExchangePointer(&g_pGSWritePos, writepos); + +// SetEvent(g_hGsEvent); +// while( g_pGSWritePos != g_pGSRingPos ) Sleep(1); + + return NULL; +#else + return writepos; +#endif + } + + SysPrintf("not enough pages %x, %d\n", mem, size); + + // BUG, the interlocked exchange add should be done in a crit section! + // dec the current pages + while(i-- > 0) { + page -= GSPAGES_MEMADDRS+1; + InterlockedExchangeAdd(page, -0x40000001); + } + + // don't have enough mem, so fall through + } +#endif + + // just copy + *(u32*)writepos = type|(((size-16)>>4)<<16); + return writepos+16; +} + +void GSRingBufVSync(int field) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + + assert( writepos + 16 <= GS_RINGBUFFEREND ); + + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos < tempbuf && writepos+16 >= tempbuf ) { + + do { + SetEvent(g_hGsEvent); + Sleep(1); + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } while(writepos < tempbuf && writepos+16 >= tempbuf ); + } + + *(u32*)writepos = GS_RINGTYPE_VSYNC; + *(int*)(writepos+4) = field; + + writepos += 16; + if( writepos == GS_RINGBUFFEREND ) writepos = GS_RINGBUFFERBASE; + InterlockedExchangePointer(&g_pGSWritePos, writepos); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); +} + +// called from gs thread or exception handler +static void GSFreeRingBuf(u8* pringbuf) +{ + u32 mem = *(u32*)(pringbuf+4) & ~0xfff; + u32* pageaddr = *(u32**)(pringbuf+8); + u32 pages = *(u32*)(pringbuf+12); + u32 val, index; + + mem &= ~0xfff; + + while(pages-- > 0 ) { + + val = pageaddr[0]; + assert( (val&0xff) > 0 ); + + index = (((val>>30)-(val&7))&3); + + if( pageaddr[ index + 1 ] != (u32)pringbuf ) { + // deleting before others, so remove it from the entry + for(val = 1; val < 5; ++val ) { + if( pageaddr[val] == (u32)pringbuf ) { + + val--; + + // shift the rest + while(index != val) { + pageaddr[1+(val)%GSPAGES_MEMADDRS] = pageaddr[(val-1)%GSPAGES_MEMADDRS+1]; + val = (val-1)%GSPAGES_MEMADDRS; + } + + break; + } + } + } + + InterlockedExchangeAdd(pageaddr, -1); + mem += 0x1000; + pageaddr += GSPAGES_MEMADDRS+1; + } +} + +void GSFreePage(u32* page) +{ + u32 indices, num; + u32 gssize; + u8* gsmem, *ringmem; + + num = *(u32*)page; + + // count approximately the size needed to be allocated + indices = ((num>>30)-(num&0xff))&3; + num &= 0xff; + gssize = 0; + + while(num-- > 0) { + // first copy to a new memory + ringmem = *(u8**)(page + 1 + indices); + gssize += (*(u32*)ringmem >> 16) << 4; + // go to the next index + indices = (indices+1)%GSPAGES_MEMADDRS; + } + + GSRingTempReserve(gssize); + + // lock section to start freeing + EnterCriticalSection(&g_PageAddrSection); + + // check again since could have changed + num = *(u32*)page; + if( (u8)num ) { + // note that values might be different + indices = ((num>>30)-(num&0xff))&3; + num &= 0xff; + + while(num-- > 0) { + // first copy to a new memory + ringmem = *(u8**)(page + 1 + indices); + + assert( !(*(u32*)ringmem & GS_RINGTYPE_MEMNOFREE) ); + + gssize = (*(u32*)ringmem >> 16) << 4; + gsmem = GSRingTempCopy(gssize); + memcpy(gsmem, *(u8**)(ringmem+4), gssize); + + GSFreeRingBuf(ringmem); + + // indicate that using different mem + *(u8**)(ringmem+4) = gsmem; + *(u32*)ringmem |= GS_RINGTYPE_MEMNOFREE; + + // go to the next index + indices = (indices+1)%GSPAGES_MEMADDRS; + } + } + + LeaveCriticalSection(&g_PageAddrSection); +} + +void gsReset() +{ + SysPrintf("GIF reset\n"); + + // GSDX crashes + //if( GSreset ) GSreset(); + memset(GS_PAGEADDRS, 0, GSPAGES_STRIDE*(0x02000000>>GS_SHIFT)); + + if( CHECK_MULTIGS ) { + ResetEvent(g_hGsEvent); + ResetEvent(g_hVuGSExit); + + g_pGSRingPos = g_pGSWritePos; + g_pGSCurFreePages = g_pGSWriteFreePages; + g_pGSTempReadPos = g_pGSTempWritePos = GS_RINGTEMPBASE; + } + + memset(g_path, 0, sizeof(g_path)); + memset(s_byRegs, 0, sizeof(s_byRegs)); + +#ifndef WIN32_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void gsGIFReset() +{ + memset(g_path, 0, sizeof(g_path)); + +#ifndef WIN32_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + if( GSgifSoftReset != NULL ) + GSgifSoftReset(7); +// else +// GSreset(); + + GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void CSRwrite(u32 value) +{ + GSwriteCSR(value); + + GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f); + + if( value & 0x100 ) { // FLUSH + //SysPrintf("GS_CSR FLUSH GS fifo: %x (CSRr=%x)\n", value, GSCSRr); + } + + CSRw |= value & ~0x60; + if (value & 0x200) { // resetGS + //GSCSRr = 0x400E; // The host FIFO neeeds to be empty too or GSsync will fail (saqib) + //GSIMR = 0xff00; + if( GSgifSoftReset != NULL ) + GSgifSoftReset(7); + else GSreset(); + + GSCSRr = 0x551B4002; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib) + //Since when!! Refraction, since 4/21/06 (zerofrog) + GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 + + // and this too (fixed megaman ac) + GSwriteCSR(GSCSRr); + } +} + +static void IMRwrite(u32 value) { + GSIMR = (value & 0x1f00)|0x6000; +} + +void gsWrite8(u32 mem, u8 value) { + switch (mem) { + case 0x12001000: // GS_CSR + CSRwrite((CSRw & ~0x000000ff) | value); break; + case 0x12001001: // GS_CSR + CSRwrite((CSRw & ~0x0000ff00) | (value << 8)); break; + case 0x12001002: // GS_CSR + CSRwrite((CSRw & ~0x00ff0000) | (value << 16)); break; + case 0x12001003: // GS_CSR + CSRwrite((CSRw & ~0xff000000) | (value << 24)); break; + default: + *PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 8 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void gsConstWrite8(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12001000: // GS_CSR + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32MtoR(ECX, (u32)&CSRw); + AND32ItoR(EAX, 0xff<<(mem&3)*8); + AND32ItoR(ECX, ~(0xff<<(mem&3)*8)); + OR32ItoR(EAX, ECX); + PUSH32R(EAX); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + default: + _eeWriteConstMem8( (u32)PS2GS_BASE(mem), mmreg ); + break; + } +} + +extern void UpdateVSyncRate(); + +void gsWrite16(u32 mem, u16 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u16*)PS2GS_BASE(mem) = value; + UpdateVSyncRate(); + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u16*)PS2GS_BASE(mem) = value; + break; + + case 0x12001000: // GS_CSR + CSRwrite( (CSRw&0xffff0000) | value); + break; + case 0x12001002: // GS_CSR + CSRwrite( (CSRw&0xffff) | ((u32)value<<16)); + break; + case 0x12001010: // GS_IMR + SysPrintf("writing to IMR 16\n"); + IMRwrite(value); + break; + + default: + *(u16*)PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 16 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void recSetSMODE1() +{ + iFlushCall(0); + AND32ItoR(EAX, 0x6000); + CMP32ItoR(EAX, 0x6000); + j8Ptr[5] = JNE8(0); + + // PAL + OR32ItoM( (u32)&Config.PsxType, 1); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // NTSC + AND32ItoM( (u32)&Config.PsxType, ~1 ); + + x86SetJ8( j8Ptr[6] ); + CALLFunc((u32)UpdateVSyncRate); +} + +void recSetSMODE2() +{ + TEST32ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // Interlaced + OR32ItoM( (u32)&Config.PsxType, 2); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // Non-Interlaced + AND32ItoM( (u32)&Config.PsxType, ~2 ); + + x86SetJ8( j8Ptr[6] ); +} + +void gsConstWrite16(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12000010: // GS_SMODE1 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + + assert( !(mem&2) ); + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + + MOV32MtoR(ECX, (u32)&CSRw); + AND32ItoR(EAX, 0xffff<<(mem&2)*8); + AND32ItoR(ECX, ~(0xffff<<(mem&2)*8)); + OR32ItoR(EAX, ECX); + PUSH32R(EAX); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + break; + } +} + +void gsWrite32(u32 mem, u32 value) +{ + assert( !(mem&3)); + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u32*)PS2GS_BASE(mem) = value; + UpdateVSyncRate(); + break; + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u32*)PS2GS_BASE(mem) = value; + break; + + case 0x12001000: // GS_CSR + CSRwrite(value); + break; + + case 0x12001010: // GS_IMR + IMRwrite(value); + break; + default: + *(u32*)PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 32 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +// (value&0x1f00)|0x6000 +void gsConstWriteIMR(int mmreg) +{ + const u32 mem = 0x12001010; + if( mmreg & MEM_XMMTAG ) { + SSE2_MOVD_XMM_to_M32((u32)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((u32)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((u32)PS2GS_BASE(mem), 0x6000); + } + else if( mmreg & MEM_MMXTAG ) { + SetMMXstate(); + MOVDMMXtoM((u32)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((u32)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((u32)PS2GS_BASE(mem), 0x6000); + } + else if( mmreg & MEM_EECONSTTAG ) { + MOV32ItoM( (u32)PS2GS_BASE(mem), (g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x1f00)|0x6000); + } + else { + AND32ItoR(mmreg, 0x1f00); + OR32ItoR(mmreg, 0x6000); + MOV32RtoM( (u32)PS2GS_BASE(mem), mmreg ); + } +} +void gsConstWrite32(u32 mem, int mmreg) { + + switch (mem) { + + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + default: + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + break; + } +} + +void gsWrite64(u32 mem, u64 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + UpdateVSyncRate(); + *(u64*)PS2GS_BASE(mem) = value; + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u64*)PS2GS_BASE(mem) = value; + break; + case 0x12001000: // GS_CSR + CSRwrite((u32)value); + break; + + case 0x12001010: // GS_IMR + IMRwrite((u32)value); + break; + + default: + *(u64*)PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 64 at %8.8lx with data %8.8lx_%8.8lx\n", mem, ((u32*)&value)[1], (u32)value); +#endif +} + +void gsConstWrite64(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + break; + } +} + +void gsConstWrite128(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + // (value&0x1f00)|0x6000 + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + break; + } +} + +u8 gsRead8(u32 mem) +{ +#ifdef HW_LOG + //HW_LOG("GS read 8 %8.8lx, at %8.8lx\n", *(u8*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u8*)PS2GS_BASE(mem); +} + +int gsConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + _eeReadConstMem8(x86reg, (u32)PS2GS_BASE(mem), sign); + return 0; +} + +u16 gsRead16(u32 mem) +{ +#ifdef HW_LOG + //HW_LOG("GS read 16 %8.8lx, at %8.8lx\n", *(u16*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u16*)PS2GS_BASE(mem); +} + +int gsConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + _eeReadConstMem16(x86reg, (u32)PS2GS_BASE(mem), sign); + return 0; +} + +u32 gsRead32(u32 mem) { + +#ifdef HW_LOG + //HW_LOG("GS read 32 %8.8lx, at %8.8lx\n", *(u32*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + return *(u32*)PS2GS_BASE(mem); +} + +int gsConstRead32(u32 x86reg, u32 mem) +{ + _eeReadConstMem32(x86reg, (u32)PS2GS_BASE(mem)); + return 0; +} + +u64 gsRead64(u32 mem) +{ +#ifdef HW_LOG + //HW_LOG("GS read 64 %8.8lx (%8.8x), at %8.8lx\n", *(u64*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u64*)PS2GS_BASE(mem); +} + +void gsConstRead64(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)PS2GS_BASE(mem)); + else { + MOVQMtoR(mmreg, (u32)PS2GS_BASE(mem)); + SetMMXstate(); + } +} + +void gsConstRead128(u32 mem, int xmmreg) +{ + _eeReadConstMem128( xmmreg, (u32)PS2GS_BASE(mem)); +} + + +void gsIrq() { + hwIntcIrq(0); +} + +static void GSRegHandlerSIGNAL(u32* data) +{ + GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + + if (CSRw & 0x1) { + GSCSRr |= 1; // signal + //CSRw &= ~1; + } + if (!(GSIMR&0x100) ) + gsIrq(); +} + +static void GSRegHandlerFINISH(u32* data) +{ + if (CSRw & 0x2) { + //CSRw &= ~2; + GSCSRr |= 2; // finish + } + if (!(GSIMR&0x200) ) + gsIrq(); +} + +static void GSRegHandlerLABEL(u32* data) +{ + GSSIGLBLID->LBLID = (GSSIGLBLID->LBLID&~data[1])|(data[0]&data[1]); +} + +typedef void (*GIFRegHandler)(u32* data); +static GIFRegHandler s_GSHandlers[3] = { GSRegHandlerSIGNAL, GSRegHandlerFINISH, GSRegHandlerLABEL }; + +// ffx pal, ntsc, jap +#define GSHACK_FFX (ElfCRC==0xbb3d833a||ElfCRC==0xa39517ab||ElfCRC==0x6A4EFE60) + +// simulates a GIF tag +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size) +{ + int nreg, i, nloop; + u32 curreg; + u32 tempreg; + GIFTAG* ptag = &g_path[path]; + +#ifdef GSCAPTURE + u32 tempcount = 0; +#endif + + if( path == 0 ) { + nloop = 0; + } + else { + nloop = ptag->nloop; + curreg = ptag->curreg; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + } + + while(size > 0) + { + if(nloop == 0) { + + ptag = (GIFTAG*)pMem; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + +#ifdef GSCAPTURE + if( g_loggs && g_gstransnum == 19 && tempcount++ > g_gslimit ) { + break; + } +#endif + + pMem+= 4; + size--; + + if(ptag->nloop == 0 ) { + if( path == 0 ) { + // ffx hack + if( GSHACK_FFX ) + continue; + } + + g_path[path].nloop = 0; + + // motogp graphics show + if( !ptag->eop ) + continue; + + return size; + } + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + s_byRegs[path][i] = tempreg&0xf; + } + + nloop = ptag->nloop; + curreg = 0; + } + + switch(ptag->flg) + { + case 0: // PACKED + { + for(; size > 0; size--, pMem += 4) + { + if( s_byRegs[path][curreg] == 0xe && (pMem[2]&0xff) >= 0x60 ) { + if( (pMem[2]&0xff) < 0x64 ) + s_GSHandlers[pMem[2]&0x3](pMem); + } + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 4; + break; + } + } + } + + if( nloop > 0 ) { + assert(size == 0); + g_path[path] = *ptag; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 1: // REGLIST + { + size *= 2; + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + assert( (tempreg&0xf) < 0x64 ); + s_byRegs[path][i] = tempreg&0xf; + } + + for(; size > 0; pMem+= 2, size--) + { + if( s_byRegs[path][curreg] >= 0x60 ) + s_GSHandlers[s_byRegs[path][curreg]&3](pMem); + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 2; + break; + } + } + } + + if( size & 1 ) pMem += 2; + size /= 2; + + if( nloop > 0 ) { + assert(size == 0); + g_path[path] = *ptag; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 2: // GIF_IMAGE (FROM_VFRAM) + case 3: + { + // simulate + if( (int)size < nloop ) { + g_path[path] = *ptag; + g_path[path].nloop = nloop-size; + return 0; + } + else { + pMem += nloop*4; + size -= nloop; + nloop = 0; + } + break; + } + } + + if( path == 0 && ptag->eop ) { + g_path[0].nloop = 0; + return size; + } + } + + g_path[path] = *ptag; + g_path[path].curreg = curreg; + g_path[path].nloop = nloop; + return size; +} + +int gsInterrupt() { +#ifdef GS_LOG + GS_LOG("gsInterrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(gif->qwc > 0) { + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("gs dma masked\n"); + return 0; + } + + dmaGIF(); + return 0; + } + + gif->chcr &= ~0x100; + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 + hwDmacIrq(DMAC_GIF); + + return 1; +} + +#ifdef GSCAPTURE +#define WRITINGDMA_TRANSFER(pMem, qwc) \ + extern u32 g_loggs, g_gstransnum, g_gsfinalnum; \ + if( !g_loggs || (g_loggs && g_gstransnum++ < g_gsfinalnum)) { \ + GSgifTransfer3(pMem, qwc-GSgifTransferDummy(2, pMem, qwc)); \ + } \ + +#else +#define WRITINGDMA_TRANSFER(pMem, qwc) GSgifTransfer3(pMem, qwc); +#endif + +#define WRITERING_DMA(pMem, qwc) { \ + if( CHECK_MULTIGS) { \ + u8* pgsmem = GSRingBufCopy(pMem, (qwc)<<4, GS_RINGTYPE_P3); \ + if( pgsmem != NULL ) { \ + memcpy_amd(pgsmem, pMem, (qwc)<<4); \ + \ + pgsmem += (qwc)<<4; \ + assert( pgsmem <= GS_RINGBUFFEREND ); \ + if( pgsmem == GS_RINGBUFFEREND ) pgsmem = GS_RINGBUFFERBASE; \ + InterlockedExchangePointer(&g_pGSWritePos, pgsmem); \ + GSgifTransferDummy(2, pMem, qwc); \ + } \ + \ + if( !CHECK_DUALCORE ) SetEvent(g_hGsEvent); \ + } \ + else { \ + FreezeMMXRegs(1); \ + FreezeXMMRegs(1); \ + WRITINGDMA_TRANSFER(pMem, qwc); \ + } \ +} \ + +int _GIFchain() { + u32 qwc = gif->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) { + // reset path3, fixes dark cloud 2 + if( GSgifSoftReset != NULL ) + GSgifSoftReset(4); + + SysPrintf("NULL GIFchain\n"); + return -1; + } + + WRITERING_DMA(pMem, qwc); + + gif->madr+= qwc*16; + gif->qwc = 0; + return (qwc)*BIAS; +} + +#define GIFchain() \ + if (gif->qwc) { \ + cycles+= _GIFchain(); /* guessing */ \ + } + +int gscount = 0; +static int prevcycles = 0; +static u32* prevtag = NULL; + +void dmaGIF() { + u32 *ptag; + int done=0; + int cycles=prevcycles; + u32 id; + + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC/* && + (gif->tadr == psHu32(0xe050))*/) { // GIF MFIFO + return; + } + if( (psHu32(GIF_CTRL) & 8) ) { + // temporarily stop + SysPrintf("Gif dma temp paused?\n"); + return; + } + +#ifdef GIF_LOG + GIF_LOG("dmaGIF chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + gif->chcr, gif->madr, gif->qwc, + gif->tadr, gif->asr0, gif->asr1); +#endif + + if (psHu32(GIF_MODE) & 0x4) { + } else + if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1) { + gif->chcr &= ~0x100; + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + hwDmacIrq(2); + return; + } + + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF + //SysPrintf("GS Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); + + if( gif->madr >= psHu32(DMAC_STADR) ) { + return; + } + } + + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x8000; //FIFO full + psHu32(GIF_STAT)|= 0xE00; // OPH=1 | APATH=3 + psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) + + if( prevcycles != 0 ) { + assert( prevtag != NULL ); + + ptag = prevtag; + // transfer interrupted, so continue + GIFchain(); + + if (gif->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + done = 1; + + } + } + + // Transfer Dn_QWC from Dn_MADR to GIF + if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode + //gscount++; + GIFchain(); + } + else { + // Chain Mode + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + cycles+=1; // Add 1 cycles from the QW read for the tag + // Transfer dma tag if tte is set + if (gif->chcr & 0x40) { + //u32 temptag[4]; +#ifdef GIF_LOG + //SysPrintf("GIF TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + +// temptag[2] = ptag[2]; +// temptag[3] = ptag[3]; +// GSgifTransfer3(temptag, 1); + } + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr); +#endif + + done = hwDmacSrcChainWithStack(gif, id); + + if (!done && (psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( gif->madr >= psHu32(DMAC_STADR) ) { + // stalled + psHu32(GIF_STAT)&= ~0x1f000E00; // OPH=0 | APATH=0 + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + prevcycles = cycles; + prevtag = ptag; + hwDmacIrq(13); + FreezeMMXRegs(0); + FreezeXMMRegs(0); + return; + } + } + + GIFchain(); //Transfers the data set by the switch + + if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("GIF TIE\n"); + + // SysPrintf("GSdmaIrq Set\n"); + done = 1; + //gif->qwc = 0; + break; + } + } + } + + prevtag = NULL; + prevcycles = 0; + INT(2, cycles); + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +static int mfifocycles; + +int mfifoGIFrbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((gif->madr+gif->qwc*16) > (maddr+msize)) { + int s1 = (maddr+msize) - gif->madr; + int s2 = gif->qwc*16 - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + WRITERING_DMA(src, s1&~15); + + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + WRITERING_DMA(src, s2&~15); + + } else { + /* it doesn't, so just transfer 'qwc*16' words + from 'gif->madr' to GS */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + + WRITERING_DMA(src, gif->qwc); + } + + gif->madr+= gif->qwc*16; + //gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); + + return 0; +} + +int mfifoGIFchain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *pMem; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (gif->qwc == 0) return 0; + + if (gif->madr >= maddr && + gif->madr < (maddr+msize)) { + if (mfifoGIFrbTransfer() == -1) return -1; + } else { + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) return -1; + + WRITERING_DMA(pMem, gif->qwc); + gif->madr+= gif->qwc*16; + } + + mfifocycles+= (gif->qwc) * BIAS; /* guessing */ + gif->qwc = 0; + + return 0; +} + +void mfifoGIFtransfer(int qwc) { + u32 *ptag; + int id; + int done = 0; + mfifocycles = 0; +#ifdef GIF_LOG + GIF_LOG("mfifoGIFtransfer qwc=0x%x\n", qwc); +#endif + if((gif->chcr & 0x100) == 0)SysPrintf("MFIFO GIF not ready %x\n", gif->chcr); + + while (qwc > 0 && done == 0) { // Loop while Dn_CHCR.STR is 1 + gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR)); + ptag = (u32*)dmaGetAddr(gif->tadr); + + id = (ptag[0] >> 28) & 0x7; + gif->qwc = (u16)ptag[0]; + gif->madr = ptag[1]; + mfifocycles += 2; + +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr); +#endif + +// if(gif->chcr & 0x40) +// GSgifTransfer3(ptag, 1); + + switch (id) { + case 0: // refe + gif->tadr += 16; + qwc = 0; + INT(11,mfifocycles); + done = 1; + break; + + case 1: // cnt + gif->madr = gif->tadr + 16; + qwc-= gif->qwc + 1; + // Set the taddr to the next tag + gif->tadr += 16 + (gif->qwc * 16); + break; + + case 3: // ref + case 4: // refs + gif->tadr += 16; + qwc--; + break; + + case 7: // end + gif->madr = gif->tadr + 16; + gif->tadr = gif->madr + (gif->qwc * 16); + qwc = 0; + INT(11,mfifocycles); + done = 1; + break; + } + + if (mfifoGIFchain() == -1) { + break; + } + + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + INT(11,mfifocycles); + //SysPrintf("mfifoGIFTransfer: dmaIrq Set\n"); + //qwc = 0; + + done = 1; + } + } + if(done == 0 && qwc == 0)hwDmacIrq(14); + /*if(qwc == 0 && gif->chcr & 0x100) { + hwDmacIrq(14); + return; + }*/ + //INT(11,cycles); + //hwDmacIrq(2); + +} + +int gifMFIFOInterrupt() { + mfifocycles = 0; + gif->chcr &= ~0x100; + hwDmacIrq(DMAC_GIF); + + return 1; +} + +extern long pDsp; +DWORD WINAPI VuGSThreadProc(LPVOID lpParam) +{ + HANDLE handles[2] = { g_hGsEvent, g_hVuGSExit }; + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + u8* writepos; + u32 tag; + u32 counter = 0; + + { + int ret; + HANDLE openhandles[2] = { g_hGSOpen, g_hVuGSExit }; + if( WaitForMultipleObjects(2, openhandles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + return 0; + } + ret = GSopen((void *)&pDsp, "PCSX2", 1); + GSCSRr = 0x551B4000; // 0x55190000 + SysPrintf("gsOpen done\n"); + if (ret != 0) { SysMessage (_("Error Opening GS Plugin")); return -1; } + SetEvent(g_hGSDone); + } + + SysPrintf("Starting GS thread\n"); + + while(1) { + + if( !CHECK_DUALCORE ) { + if( WaitForMultipleObjects(2, handles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + GSclose(); + return 0; + } + } + else if( (counter++ & 0xffff) == 0 ) { + if( WaitForSingleObject(g_hVuGSExit, 0) == WAIT_OBJECT_0 ) { + GSclose(); + return 0; + } + } + + if( g_pGSRingPos != g_pGSWritePos ) { + + do { + writepos = *(volatile PU8*)&g_pGSWritePos; + + while( g_pGSRingPos != writepos ) { + + assert( g_pGSRingPos < GS_RINGBUFFEREND ); + // process until writepos + tag = *(u32*)g_pGSRingPos; + + switch( tag&0xffff ) { + case GS_RINGTYPE_RESTART: + InterlockedExchangePointer(&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( GS_RINGBUFFERBASE == writepos ) + goto ExitGS; + + continue; + + case GS_RINGTYPE_P1: + GSgifTransfer1((u32*)(g_pGSRingPos+16), 0); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + + case GS_RINGTYPE_P2: + GSgifTransfer2((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_P3: + GSgifTransfer3((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_VSYNC: + GSvsync(*(int*)(g_pGSRingPos+4)); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + +#ifdef GS_ENABLE_CACHING + case GS_RINGTYPE_P2|GS_RINGTYPE_MEMREF: + case GS_RINGTYPE_P2|GS_RINGTYPE_MEMREF|GS_RINGTYPE_MEMNOFREE: + EnterCriticalSection(&g_PageAddrSection); + + // read again since could have changed + tag = *(u32*)g_pGSRingPos; + + GSgifTransfer2(*(u32**)(g_pGSRingPos+4), tag>>16); + + if( ENABLE_GS_CACHING ) { + if( !(tag & GS_RINGTYPE_MEMNOFREE) ) { + GSFreeRingBuf(g_pGSRingPos); + } + else { + // using temp memory, so release + g_pGSTempReadPos = *(u8**)(g_pGSRingPos+4) + ((tag>>16)<<4); + } + } + + LeaveCriticalSection(&g_PageAddrSection); + +#ifdef _RINGBUF_DEBUG + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); +#else + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); +#endif + + break; + case GS_RINGTYPE_P3|GS_RINGTYPE_MEMREF: + case GS_RINGTYPE_P3|GS_RINGTYPE_MEMREF|GS_RINGTYPE_MEMNOFREE: + + EnterCriticalSection(&g_PageAddrSection); + + // read again since could have changed + tag = *(u32*)g_pGSRingPos; + +#ifdef _RINGBUF_DEBUG + assert( memcmp(*(u32**)(g_pGSRingPos+4), g_pGSRingPos+16, (tag>>16)*16) == 0 ); +#endif + GSgifTransfer3(*(u32**)(g_pGSRingPos+4), tag>>16); + + if( ENABLE_GS_CACHING ) { + if( !(tag & GS_RINGTYPE_MEMNOFREE) ) { + GSFreeRingBuf(g_pGSRingPos); + } + else { + // using temp memory, so release + g_pGSTempReadPos = *(u8**)(g_pGSRingPos+4) + ((tag>>16)<<4); + } + } + + LeaveCriticalSection(&g_PageAddrSection); + +#ifdef _RINGBUF_DEBUG + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); +#else + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); +#endif + break; + +#endif // end GS_ENABLE_CACHING + + case GS_RINGTYPE_VIFFIFO: + { + u64* pMem; + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + pMem = (u64*)dmaGetAddr(vif1ch->madr); + + if (pMem == NULL) { + psHu32(DMAC_STAT)|= 1<<15; + break; + } + GSreadFIFO2(pMem, tag>>16); + + // set incase read + psHu64(0x5000) = pMem[2*(tag>>16)-2]; + psHu64(0x5008) = pMem[2*(tag>>16)-1]; + + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + tag = (tag>>16) - (cpuRegs.cycle- *(u32*)(g_pGSRingPos+8)); + if( tag & 0x80000000 ) tag = 0; + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + + INT(1, tag); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + } + + default: + + SysPrintf("VsGSThreadProc, bad packet\n"); + g_pGSRingPos = g_pGSWritePos; + //flushall(); + } + + assert( g_pGSRingPos <= GS_RINGBUFFEREND ); + if( g_pGSRingPos == GS_RINGBUFFEREND ) + InterlockedExchangePointer(&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( g_pGSRingPos == g_pGSWritePos ) { + break; + } + } +ExitGS: + ; + } while(g_pGSRingPos != *(volatile PU8*)&g_pGSWritePos); + } + + // process vu1 + } + + return 0; +} + +int gsFreeze(gzFile f, int Mode) { + + gzfreeze(PS2MEM_GS, 0x2000); + gzfreeze(&CSRw, sizeof(CSRw)); + gzfreeze(g_path, sizeof(g_path)); + gzfreeze(s_byRegs, sizeof(s_byRegs)); + + return 0; +} + +#undef GIFchain \ No newline at end of file diff --git a/GS.h b/GS.h new file mode 100644 index 0000000000..e08eb111f7 --- /dev/null +++ b/GS.h @@ -0,0 +1,126 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +#include "Common.h" + +typedef struct +{ + u32 SIGID; + u32 LBLID; +} GSRegSIGBLID; + +#ifdef WIN32_VIRTUAL_MEM +#define GSCSRr *((u64*)(PS2MEM_GS+0x1000)) +#define GSIMR *((u32*)(PS2MEM_GS+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(PS2MEM_GS+0x1080)) +#else +extern u8 g_RealGSMem[0x2000]; +#define GSCSRr *((u64*)(g_RealGSMem+0x1000)) +#define GSIMR *((u32*)(g_RealGSMem+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(g_RealGSMem+0x1080)) +#endif + +#define GS_RINGBUFFERBASE (u8*)(0x10200000) +#define GS_RINGBUFFERSIZE 0x00200000 // 2Mb +#define GS_RINGBUFFEREND (u8*)(GS_RINGBUFFERBASE+GS_RINGBUFFERSIZE) + +#define GS_RINGTEMPBASE (u8*)(0x10400000) +#define GS_RINGTEMPSIZE 0x00100000 // 1Mb +#define GS_RINGTEMPEND (u8*)(GS_RINGTEMPBASE+GS_RINGTEMPSIZE) + +#define GS_SHIFT 12 +#define ENABLE_GS_CACHING 0 // set to 0 to disable + +// mem addrs to support +#define GSPAGES_MEMADDRS 4 +#define GSPAGES_STRIDE ((1+GSPAGES_MEMADDRS)*4) +#define GS_PAGEADDRS_ 0x10500000 +#define GS_PAGEADDRS (u32*)(GS_PAGEADDRS_) + +#define GS_RINGTYPE_RESTART 0 +#define GS_RINGTYPE_P1 1 +#define GS_RINGTYPE_P2 2 +#define GS_RINGTYPE_P3 3 +#define GS_RINGTYPE_VSYNC 4 +#define GS_RINGTYPE_VIFFIFO 5 // GSreadFIFO2 +#define GS_RINGTYPE_MEMREF 0x10 // if bit set, memory is preserved (only valid for p2/p3) +#define GS_RINGTYPE_MEMNOFREE 0x20 // if bit set, don't free or mem + +// if returns NULL, don't copy (memory is preserved) +u8* GSRingBufCopy(void* mem, u32 size, u32 type); +void GSRingBufVSync(int field); +void GSFreePage(u32* pGSPage); + +extern u8* g_pGSWritePos; + +// mem and size are the ones from GSRingBufCopy +#define GSRINGBUF_DONECOPY(mem, size) { \ + u8* temp = (u8*)(mem) + (size); \ + if( temp == GS_RINGBUFFEREND ) temp = GS_RINGBUFFERBASE; \ + InterlockedExchangePointer(&g_pGSWritePos, temp); \ +} + +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size); + +void gsInit(); +void gsShutdown(); +void gsReset(); + +// used for resetting GIF fifo +void gsGIFReset(); + +void gsWrite8(u32 mem, u8 value); +void gsConstWrite8(u32 mem, int mmreg); + +void gsWrite16(u32 mem, u16 value); +void gsConstWrite16(u32 mem, int mmreg); + +void gsWrite32(u32 mem, u32 value); +void gsConstWrite32(u32 mem, int mmreg); + +void gsWrite64(u32 mem, u64 value); +void gsConstWrite64(u32 mem, int mmreg); + +void gsConstWrite128(u32 mem, int mmreg); + +u8 gsRead8(u32 mem); +int gsConstRead8(u32 x86reg, u32 mem, u32 sign); + +u16 gsRead16(u32 mem); +int gsConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 gsRead32(u32 mem); +int gsConstRead32(u32 x86reg, u32 mem); + +u64 gsRead64(u32 mem); +void gsConstRead64(u32 mem, int mmreg); + +void gsConstRead128(u32 mem, int xmmreg); + +void gsIrq(); +int gsInterrupt(); +void dmaGIF(); +void mfifoGIFtransfer(int qwc); +int gsFreeze(gzFile f, int Mode); +int _GIFchain(); +int gifMFIFOInterrupt(); + +#endif diff --git a/Gte.c b/Gte.c new file mode 100644 index 0000000000..d4e75c42cc --- /dev/null +++ b/Gte.c @@ -0,0 +1,2846 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Gte.h" +#include "PsxCommon.h" + +#ifdef GTE_DUMP +#define G_OP(name,delay) fprintf(gteLog, "* : %08X : %02d : %s\n", psxRegs.code, delay, name); +#define G_SD(reg) fprintf(gteLog, "+D%02d : %08X\n", reg, psxRegs.CP2D.r[reg]); +#define G_SC(reg) fprintf(gteLog, "+C%02d : %08X\n", reg, psxRegs.CP2C.r[reg]); +#define G_GD(reg) fprintf(gteLog, "-D%02d : %08X\n", reg, psxRegs.CP2D.r[reg]); +#define G_GC(reg) fprintf(gteLog, "-C%02d : %08X\n", reg, psxRegs.CP2C.r[reg]); +#else +#define G_OP(name,delay) +#define G_SD(reg) +#define G_SC(reg) +#define G_GD(reg) +#define G_GC(reg) +#endif + +#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define gteVX0 ((s16*)psxRegs.CP2D.r)[0] +#define gteVY0 ((s16*)psxRegs.CP2D.r)[1] +#define gteVZ0 ((s16*)psxRegs.CP2D.r)[2] +#define gteVX1 ((s16*)psxRegs.CP2D.r)[4] +#define gteVY1 ((s16*)psxRegs.CP2D.r)[5] +#define gteVZ1 ((s16*)psxRegs.CP2D.r)[6] +#define gteVX2 ((s16*)psxRegs.CP2D.r)[8] +#define gteVY2 ((s16*)psxRegs.CP2D.r)[9] +#define gteVZ2 ((s16*)psxRegs.CP2D.r)[10] +#define gteRGB psxRegs.CP2D.r[6] +#define gteOTZ ((s16*)psxRegs.CP2D.r)[7*2] +#define gteIR0 ((s32*)psxRegs.CP2D.r)[8] +#define gteIR1 ((s32*)psxRegs.CP2D.r)[9] +#define gteIR2 ((s32*)psxRegs.CP2D.r)[10] +#define gteIR3 ((s32*)psxRegs.CP2D.r)[11] +#define gteSX0 ((s16*)psxRegs.CP2D.r)[12*2] +#define gteSY0 ((s16*)psxRegs.CP2D.r)[12*2+1] +#define gteSX1 ((s16*)psxRegs.CP2D.r)[13*2] +#define gteSY1 ((s16*)psxRegs.CP2D.r)[13*2+1] +#define gteSX2 ((s16*)psxRegs.CP2D.r)[14*2] +#define gteSY2 ((s16*)psxRegs.CP2D.r)[14*2+1] +#define gteSXP ((s16*)psxRegs.CP2D.r)[15*2] +#define gteSYP ((s16*)psxRegs.CP2D.r)[15*2+1] +#define gteSZx ((u16*)psxRegs.CP2D.r)[16*2] +#define gteSZ0 ((u16*)psxRegs.CP2D.r)[17*2] +#define gteSZ1 ((u16*)psxRegs.CP2D.r)[18*2] +#define gteSZ2 ((u16*)psxRegs.CP2D.r)[19*2] +#define gteRGB0 psxRegs.CP2D.r[20] +#define gteRGB1 psxRegs.CP2D.r[21] +#define gteRGB2 psxRegs.CP2D.r[22] +#define gteMAC0 psxRegs.CP2D.r[24] +#define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] +#define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] +#define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] +#define gteIRGB psxRegs.CP2D.r[28] +#define gteORGB psxRegs.CP2D.r[29] +#define gteLZCS psxRegs.CP2D.r[30] +#define gteLZCR psxRegs.CP2D.r[31] + +#define gteR ((u8 *)psxRegs.CP2D.r)[6*4] +#define gteG ((u8 *)psxRegs.CP2D.r)[6*4+1] +#define gteB ((u8 *)psxRegs.CP2D.r)[6*4+2] +#define gteCODE ((u8 *)psxRegs.CP2D.r)[6*4+3] +#define gteC gteCODE + +#define gteR0 ((u8 *)psxRegs.CP2D.r)[20*4] +#define gteG0 ((u8 *)psxRegs.CP2D.r)[20*4+1] +#define gteB0 ((u8 *)psxRegs.CP2D.r)[20*4+2] +#define gteCODE0 ((u8 *)psxRegs.CP2D.r)[20*4+3] +#define gteC0 gteCODE0 + +#define gteR1 ((u8 *)psxRegs.CP2D.r)[21*4] +#define gteG1 ((u8 *)psxRegs.CP2D.r)[21*4+1] +#define gteB1 ((u8 *)psxRegs.CP2D.r)[21*4+2] +#define gteCODE1 ((u8 *)psxRegs.CP2D.r)[21*4+3] +#define gteC1 gteCODE1 + +#define gteR2 ((u8 *)psxRegs.CP2D.r)[22*4] +#define gteG2 ((u8 *)psxRegs.CP2D.r)[22*4+1] +#define gteB2 ((u8 *)psxRegs.CP2D.r)[22*4+2] +#define gteCODE2 ((u8 *)psxRegs.CP2D.r)[22*4+3] +#define gteC2 gteCODE2 + + + +#define gteR11 ((s16*)psxRegs.CP2C.r)[0] +#define gteR12 ((s16*)psxRegs.CP2C.r)[1] +#define gteR13 ((s16*)psxRegs.CP2C.r)[2] +#define gteR21 ((s16*)psxRegs.CP2C.r)[3] +#define gteR22 ((s16*)psxRegs.CP2C.r)[4] +#define gteR23 ((s16*)psxRegs.CP2C.r)[5] +#define gteR31 ((s16*)psxRegs.CP2C.r)[6] +#define gteR32 ((s16*)psxRegs.CP2C.r)[7] +#define gteR33 ((s16*)psxRegs.CP2C.r)[8] +#define gteTRX ((s32*)psxRegs.CP2C.r)[5] +#define gteTRY ((s32*)psxRegs.CP2C.r)[6] +#define gteTRZ ((s32*)psxRegs.CP2C.r)[7] +#define gteL11 ((s16*)psxRegs.CP2C.r)[16] +#define gteL12 ((s16*)psxRegs.CP2C.r)[17] +#define gteL13 ((s16*)psxRegs.CP2C.r)[18] +#define gteL21 ((s16*)psxRegs.CP2C.r)[19] +#define gteL22 ((s16*)psxRegs.CP2C.r)[20] +#define gteL23 ((s16*)psxRegs.CP2C.r)[21] +#define gteL31 ((s16*)psxRegs.CP2C.r)[22] +#define gteL32 ((s16*)psxRegs.CP2C.r)[23] +#define gteL33 ((s16*)psxRegs.CP2C.r)[24] +#define gteRBK ((s32*)psxRegs.CP2C.r)[13] +#define gteGBK ((s32*)psxRegs.CP2C.r)[14] +#define gteBBK ((s32*)psxRegs.CP2C.r)[15] +#define gteLR1 ((s16*)psxRegs.CP2C.r)[32] +#define gteLR2 ((s16*)psxRegs.CP2C.r)[33] +#define gteLR3 ((s16*)psxRegs.CP2C.r)[34] +#define gteLG1 ((s16*)psxRegs.CP2C.r)[35] +#define gteLG2 ((s16*)psxRegs.CP2C.r)[36] +#define gteLG3 ((s16*)psxRegs.CP2C.r)[37] +#define gteLB1 ((s16*)psxRegs.CP2C.r)[38] +#define gteLB2 ((s16*)psxRegs.CP2C.r)[39] +#define gteLB3 ((s16*)psxRegs.CP2C.r)[40] +#define gteRFC ((s32*)psxRegs.CP2C.r)[21] +#define gteGFC ((s32*)psxRegs.CP2C.r)[22] +#define gteBFC ((s32*)psxRegs.CP2C.r)[23] +#define gteOFX ((s32*)psxRegs.CP2C.r)[24] +#define gteOFY ((s32*)psxRegs.CP2C.r)[25] +#define gteH ((u16*)psxRegs.CP2C.r)[52] +#define gteDQA ((s16*)psxRegs.CP2C.r)[54] +#define gteDQB ((s32*)psxRegs.CP2C.r)[28] +#define gteZSF3 ((s16*)psxRegs.CP2C.r)[58] +#define gteZSF4 ((s16*)psxRegs.CP2C.r)[60] +#define gteFLAG psxRegs.CP2C.r[31] + +__inline unsigned long MFC2(int reg) { + switch(reg) { + case 29: + gteORGB = (gteIR1 ) | + (gteIR2 << 5) | + (gteIR3 << 10); +// gteORGB = ((gteIR1 & 0xf80)>>7) | +// ((gteIR2 & 0xf80)>>2) | +// ((gteIR3 & 0xf80)<<3); + return gteORGB; + + default: + return psxRegs.CP2D.r[reg]; + } +} + +__inline void MTC2(unsigned long value, int reg) { + int a; + + switch(reg) { + case 8: case 9: case 10: case 11: + psxRegs.CP2D.r[reg] = (short)value; + break; + + case 15: + psxRegs.CP2D.r[12] = psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13] = psxRegs.CP2D.r[14]; + psxRegs.CP2D.r[14] = value; + psxRegs.CP2D.r[15] = value; + break; + + case 16: case 17: case 18: case 19: + psxRegs.CP2D.r[reg] = (value & 0xffff); + break; + + case 28: + psxRegs.CP2D.r[28] = value; + gteIR1 = (value ) & 0x1f; + gteIR2 = (value >> 5) & 0x1f; + gteIR3 = (value >> 10) & 0x1f; +// gteIR1 = ((value ) & 0x1f) << 4; +// gteIR2 = ((value >> 5) & 0x1f) << 4; +// gteIR3 = ((value >> 10) & 0x1f) << 4; + break; + + case 30: + psxRegs.CP2D.r[30] = value; + + a = psxRegs.CP2D.r[30]; +#if defined(__MSCW32__) && !defined(__VCNET2005__) + if (a > 0) { + __asm { + mov eax, a; + bsr eax, eax; + mov a, eax; + } + psxRegs.CP2D.r[31] = 31 - a; + } else if (a < 0) { + __asm { + mov eax, a; + xor eax, 0xffffffff; + bsr eax, eax; + mov a, eax; + } + psxRegs.CP2D.r[31] = 31 - a; + } else { + psxRegs.CP2D.r[31] = 32; + } +#elif defined(__GNUC__) + if (a > 0) { + __asm__ ("bsrl %1, %0\n" : "=r"(a) : "r"(a) ); + psxRegs.CP2D.r[31] = 31 - a; + } else if (a < 0) { + a^= 0xffffffff; + __asm__ ("bsrl %1, %0\n" : "=r"(a) : "r"(a) ); + psxRegs.CP2D.r[31] = 31 - a; + } else { + psxRegs.CP2D.r[31] = 32; + } +#else + if (a > 0) { + int i; + for (i=31; (a & (1 << i)) == 0 && i >= 0; i--); + psxRegs.CP2D.r[31] = 31 - i; + } else if (a < 0) { + int i; + a^= 0xffffffff; + for (i=31; (a & (1 << i)) == 0 && i >= 0; i--); + psxRegs.CP2D.r[31] = 31 - i; + } else { + psxRegs.CP2D.r[31] = 32; + } +#endif + break; + + default: + psxRegs.CP2D.r[reg] = value; + } +} + +void gteMFC2() { + if (!_Rt_) return; + psxRegs.GPR.r[_Rt_] = MFC2(_Rd_); +} + +void gteCFC2() { + if (!_Rt_) return; + psxRegs.GPR.r[_Rt_] = psxRegs.CP2C.r[_Rd_]; +} + +void gteMTC2() { + MTC2(psxRegs.GPR.r[_Rt_], _Rd_); +} + +void gteCTC2() { + psxRegs.CP2C.r[_Rd_] = psxRegs.GPR.r[_Rt_]; +} + +#define _oB_ (psxRegs.GPR.r[_Rs_] + _Imm_) + +void gteLWC2() { + MTC2(psxMemRead32(_oB_), _Rt_); +} + +void gteSWC2() { + psxMemWrite32(_oB_, MFC2(_Rt_)); +} + +/////LIMITATIONS AND OTHER STUFF************************************ +#define MAC2IR() \ +{ \ + if (gteMAC1 < (long)(-32768)) { gteIR1=(long)(-32768); gteFLAG|=1<<24;} \ + else \ + if (gteMAC1 > (long)( 32767)) { gteIR1=(long)( 32767); gteFLAG|=1<<24;} \ + else gteIR1=(long)gteMAC1; \ + if (gteMAC2 < (long)(-32768)) { gteIR2=(long)(-32768); gteFLAG|=1<<23;} \ + else \ + if (gteMAC2 > (long)( 32767)) { gteIR2=(long)( 32767); gteFLAG|=1<<23;} \ + else gteIR2=(long)gteMAC2; \ + if (gteMAC3 < (long)(-32768)) { gteIR3=(long)(-32768); gteFLAG|=1<<22;} \ + else \ + if (gteMAC3 > (long)( 32767)) { gteIR3=(long)( 32767); gteFLAG|=1<<22;} \ + else gteIR3=(long)gteMAC3; \ +} + + +#define MAC2IR1() \ +{ \ + if (gteMAC1 < (long)0) { gteIR1=(long)0; gteFLAG|=1<<24;} \ + else if (gteMAC1 > (long)(32767)) { gteIR1=(long)(32767); gteFLAG|=1<<24;} \ + else gteIR1=(long)gteMAC1; \ + if (gteMAC2 < (long)0) { gteIR2=(long)0; gteFLAG|=1<<23;} \ + else if (gteMAC2 > (long)(32767)) { gteIR2=(long)(32767); gteFLAG|=1<<23;} \ + else gteIR2=(long)gteMAC2; \ + if (gteMAC3 < (long)0) { gteIR3=(long)0; gteFLAG|=1<<22;} \ + else if (gteMAC3 > (long)(32767)) { gteIR3=(long)(32767); gteFLAG|=1<<22;} \ + else gteIR3=(long)gteMAC3; \ +} + + + +/* +#define MAGIC (((65536. * 65536. * 16) + (65536.*.5)) * 65536.) + +static __inline long float2int(double d) +{ + double dtemp = MAGIC + d; + return (*(long *)&dtemp)-0x80000000; +}*/ +__inline double NC_OVERFLOW1(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<29;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<26;} + + return x; +} + +__inline double NC_OVERFLOW2(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<28;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<25;} + + return x; +} + +__inline double NC_OVERFLOW3(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<27;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<24;} + + return x; +} + +__inline double NC_OVERFLOW4(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<16;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<15;} + + return x; +} +/* +__inline double EDETEC1(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<30; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<27; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC2(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<29; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<26; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC3(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<28; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<25; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC4(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<16; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<15; return (double) 2147483647;} + + else return data; +}*/ +/* +double LimitAU(double fraction,unsigned long bitIndex) { + if (fraction < 0.0) { fraction = 0.0; gteFLAG |= (1< 32767.0) { fraction = 32767.0; gteFLAG |= (1< 32767.0) { fraction = 32767.0; gteFLAG |= (1< 255.0) { fraction = 255.0; gteFLAG |= (1< 65535.0) { fraction = 65535.0; gteFLAG |= (1< 1023.0) { fraction = 1023.0; gteFLAG |= (1< 1023.0) { fraction = 1023.0; gteFLAG |= (1<MAX) {gteFLAG|=1<MAX) return MAX; + + else return data; +} + +double OLIMIT(double data) +{ + data=(data); + + if (data<(double)-2147483647) {return (double)-2147483647;} + else + if (data>(double) 2147483647) {return (double) 2147483647;} + + else return data; +}*/ + +double limA1S(double x) { + + if (x <-32768.0) { x =-32768.0; gteFLAG |= (1<<24); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<24); } return (x); +} + +double limA2S(double x) { + + if (x <-32768.0) { x =-32768.0; gteFLAG |= (1<<23); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<23); } return (x); +} + +double limA3S(double x) { + + if (x <-32768.0) { x =-32768.0; gteFLAG |= (1<<22); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<22); } return (x); +} + +double limA1U(double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<24); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<24); } return (x); +} + +double limA2U(double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<23); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<23); } return (x); +} + +double limA3U(double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<22); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<22); } return (x); +} + +double limB1 (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<21); } else + if (x > 255.0) { x = 255.0; gteFLAG |= (1<<21); } return (x); +} + +double limB2 (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<20); } else + if (x > 255.0) { x = 255.0; gteFLAG |= (1<<20); } return (x); +} + +double limB3 (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<19); } else + if (x > 255.0) { x = 255.0; gteFLAG |= (1<<19); } return (x); +} + +double limC (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<18); } else + if (x > 65535.0) { x = 65535.0; gteFLAG |= (1<<18); } return (x); +} + +double limD1 (double x) { + + if (x < 1024.0) { x = 1024.0; gteFLAG |= (1<<14); } else + if (x > 1023.0) { x = 1023.0; gteFLAG |= (1<<14); } return (x); +} + +double limD2 (double x) { + + if (x < 1024.0) { x = 1024.0; gteFLAG |= (1<<13); } else + if (x > 1023.0) { x = 1023.0; gteFLAG |= (1<<13); } return (x); +} + +double limE (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<12); } else + if (x > 4095.0) { x = 4095.0; gteFLAG |= (1<<12); } return (x); +} + +double limG1(double x) { + + if (x > 2147483647.0f) { gteFLAG |= (1<<16); } else + if (x <-2147483648.0f) { gteFLAG |= (1<<15); } + + if (x > 1023.0f) { x = 1023.0f; gteFLAG |= (1<<14); } else + if (x < -1024.0f) { x = -1024.0f; gteFLAG |= (1<<14); } return (x); +} + +double limG2(double x) { + + if (x > 2147483647.0f) { gteFLAG |= (1<<16); } else + if (x <-2147483648.0f) { gteFLAG |= (1<<15); } + + if (x > 1023.0f) { x = 1023.0f; gteFLAG |= (1<<13); } else + if (x < -1024.0f) { x = -1024.0f; gteFLAG |= (1<<13); } return (x); +} + +//********END OF LIMITATIONS**********************************/ + +void gteRTPS() { +// double SSX0,SSY0,SSZ0; +// double SZ; + double DSZ; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_RTPS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("RTPS", 14); + G_SD(0); + G_SD(1); + + G_SD(16); // Store original fifo + G_SD(17); + G_SD(18); + G_SD(19); + + G_SC(0); + G_SC(1); + G_SC(2); + G_SC(3); + G_SC(4); + G_SC(5); + G_SC(6); + G_SC(7); + + G_SC(24); + G_SC(25); + G_SC(26); + G_SC(27); + G_SC(28); + } +#endif +/* gteFLAG = 0; + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX0*gteR11) + (double)(gteVY0*gteR12) + (double)(gteVZ0*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX0*gteR21) + (double)(gteVY0*gteR22) + (double)(gteVZ0*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX0*gteR31) + (double)(gteVY0*gteR32) + (double)(gteVZ0*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ0 = gteSZ1; + gteSZ1 = gteSZ2; + gteSZ2 = gteSZx; + gteSZx = (unsigned short)float2int(SZ); + + psxRegs.CP2D.r[12]= psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13]= psxRegs.CP2D.r[14]; + + gteSX2 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1024,14)); + gteSY2 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1024,13)); + + gteMAC1 = (signed long)(SSX0); + gteMAC2 = (signed long)(SSY0); + gteMAC3 = (signed long)(SSZ0); + + MAC2IR(); + + gteMAC0 = (signed long)float2int(OLIMIT((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*16777216)); + gteIR0 = (signed long)float2int(LIMIT(((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*4096),(double)0,(double)4095,12)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + gteSZx = gteSZ0; + gteSZ0 = gteSZ1; + gteSZ1 = gteSZ2; + gteSZ2 = limC(gteMAC3); + + psxRegs.CP2D.r[12]= psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13]= psxRegs.CP2D.r[14]; + + DSZ = (double)gteH / gteSZ2; + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ) * 4096.0); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(8); + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(12); + //G_GD(13); + G_GD(14); + + G_GD(16); + G_GD(17); + G_GD(18); + G_GD(19); + + G_GD(24); + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteRTPT() { +// double SSX0,SSY0,SSZ0; +// double SZ; + double DSZ; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_RTPT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("RTPT", 22); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + + G_SD(16); // Store original fifo + G_SD(17); + G_SD(18); + G_SD(19); + + G_SC(0); + G_SC(1); + G_SC(2); + G_SC(3); + G_SC(4); + G_SC(5); + G_SC(6); + G_SC(7); + + G_SC(24); + G_SC(25); + G_SC(26); + G_SC(27); + G_SC(28); + } +#endif +/* gteFLAG = 0; + + gteSZ0 = gteSZx; + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX0 * gteR11) + (double)(gteVY0 * gteR12) + (double)(gteVZ0 * gteR13)) / 4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX0 * gteR21) + (double)(gteVY0 * gteR22) + (double)(gteVZ0 * gteR23)) / 4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX0 * gteR31) + (double)(gteVY0 * gteR32) + (double)(gteVZ0 * gteR33)) / 4096.0); + + SZ = LIMIT(SSZ0, (double)0, (double)65535, 18); + DSZ = ((double)gteH / SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ1 = (unsigned short)float2int(SZ); + gteSX0 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY0 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX1*gteR11) + (double)(gteVY1*gteR12) + (double)(gteVZ1*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX1*gteR21) + (double)(gteVY1*gteR22) + (double)(gteVZ1*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX1*gteR31) + (double)(gteVY1*gteR32) + (double)(gteVZ1*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ2 = (unsigned short)float2int(SZ); + gteSX1 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY1 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX2*gteR11) + (double)(gteVY2*gteR12) + (double)(gteVZ2*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX2*gteR21) + (double)(gteVY2*gteR22) + (double)(gteVZ2*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX2*gteR31) + (double)(gteVY2*gteR32) + (double)(gteVZ2*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZx = (unsigned short)float2int(SZ); + gteSX2 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY2 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + gteMAC1 = (signed long)float2int(SSX0); + gteMAC2 = (signed long)float2int(SSY0); + gteMAC3 = (signed long)float2int(SSZ0); + + MAC2IR(); + + gteMAC0 = (signed long)float2int(OLIMIT((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*16777216)); + gteIR0 = (signed long)float2int(LIMIT(((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*4096),(double)0,(double)4095,12)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + /* NC: old + gteFLAG = 0; + + gteSZ0 = gteSZx; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ1 = limC(gteMAC3); + + gteSX0 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY0 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX1 + gteR12*gteVY1 + gteR13*gteVZ1)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX1 + gteR22*gteVY1 + gteR23*gteVZ1)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX1 + gteR32*gteVY1 + gteR33*gteVZ1)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ2 = limC(gteMAC3); + + gteSX1 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY1 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX2 + gteR12*gteVY2 + gteR13*gteVZ2)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX2 + gteR22*gteVY2 + gteR23*gteVZ2)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX2 + gteR32*gteVY2 + gteR33*gteVZ2)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); if (DSZ > 2147483647.0f) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZx = gteSZ2; + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 4096.0f); + */ + + gteFLAG = 0; + + gteSZx = gteSZ2; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ0 = limC(gteMAC3); + + gteSX0 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY0 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX1 + gteR12*gteVY1 + gteR13*gteVZ1)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX1 + gteR22*gteVY1 + gteR23*gteVZ1)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX1 + gteR32*gteVY1 + gteR33*gteVZ1)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ1 = limC(gteMAC3); + + gteSX1 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY1 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX2 + gteR12*gteVY2 + gteR13*gteVZ2)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX2 + gteR22*gteVY2 + gteR23*gteVZ2)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX2 + gteR32*gteVY2 + gteR33*gteVZ2)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0f) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ2 = limC(gteMAC3); + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 4096.0f); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(8); + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(12); + G_GD(13); + G_GD(14); + + G_GD(16); + G_GD(17); + G_GD(18); + G_GD(19); + + G_GD(24); + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define gte_C11 gteLR1 +#define gte_C12 gteLR2 +#define gte_C13 gteLR3 +#define gte_C21 gteLG1 +#define gte_C22 gteLG2 +#define gte_C23 gteLG3 +#define gte_C31 gteLB1 +#define gte_C32 gteLB2 +#define gte_C33 gteLB3 + +#define _MVMVA_FUNC(_v0, _v1, _v2, mx) { \ + SSX = (_v0) * mx##11 + (_v1) * mx##12 + (_v2) * mx##13; \ + SSY = (_v0) * mx##21 + (_v1) * mx##22 + (_v2) * mx##23; \ + SSZ = (_v0) * mx##31 + (_v1) * mx##32 + (_v2) * mx##33; \ +} + +void gteMVMVA() { + double SSX, SSY, SSZ; + +#ifdef GTE_LOG + GTE_LOG("GTE_MVMVA %lx\n", psxRegs.code & 0x1ffffff); +#endif + + switch (psxRegs.code & 0x78000) { + case 0x00000: // V0 * R + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gteR); break; + case 0x08000: // V1 * R + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gteR); break; + case 0x10000: // V2 * R + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gteR); break; + case 0x18000: // IR * R + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gteR); + break; + case 0x20000: // V0 * L + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gteL); break; + case 0x28000: // V1 * L + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gteL); break; + case 0x30000: // V2 * L + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gteL); break; + case 0x38000: // IR * L + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gteL); break; + case 0x40000: // V0 * C + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gte_C); break; + case 0x48000: // V1 * C + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gte_C); break; + case 0x50000: // V2 * C + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gte_C); break; + case 0x58000: // IR * C + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gte_C); break; + default: + SSX = SSY = SSZ = 0; + } + + if (psxRegs.code & 0x80000) { + SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + SSX+= gteTRX; + SSY+= gteTRY; + SSZ+= gteTRZ; + break; + case 0x2000: // Add BK + SSX+= gteRBK; + SSY+= gteGBK; + SSZ+= gteBBK; + break; + case 0x4000: // Add FC + SSX+= gteRFC; + SSY+= gteGFC; + SSZ+= gteBFC; + break; + } + + gteFLAG = 0; + //gteMAC1 = (long)SSX; + //gteMAC2 = (long)SSY; + //gteMAC3 = (long)SSZ;//okay the follow lines are correct?? + gteMAC1=NC_OVERFLOW1(SSX); + gteMAC2=NC_OVERFLOW2(SSY); + gteMAC3=NC_OVERFLOW3(SSZ); + if (psxRegs.code & 0x400) + MAC2IR1() + else MAC2IR() + + SUM_FLAG; +} + +void gteNCLIP() { +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCLIP\n"); +#endif + + //gteLog + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCLIP", 8); + G_SD(12); + G_SD(13); + G_SD(14); + } +#endif + +/* gteFLAG = 0; + + gteMAC0 = (signed long)float2int(EDETEC4( + ((double)gteSX0*((double)gteSY1-(double)gteSY2))+ + ((double)gteSX1*((double)gteSY2-(double)gteSY0))+ + ((double)gteSX2*((double)gteSY0-(double)gteSY1)))); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + + gteMAC0 = gteSX0 * (gteSY1 - gteSY2) + + gteSX1 * (gteSY2 - gteSY0) + + gteSX2 * (gteSY0 - gteSY1); + + //gteMAC0 = (gteSX0 - gteSX1) * (gteSY0 - gteSY2) - (gteSX0 - gteSX2) * (gteSY0 - gteSY1); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(24); + G_GC(31); + } +#endif +} + +void gteAVSZ3() { +// unsigned long SS; +// double SZ1,SZ2,SZ3; +// double ZSF3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_AVSZ3\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("AVSZ3", 5); + G_SD(16); + G_SD(17); + G_SD(18); + G_SD(19); + G_SC(29); + G_SC(30); + } +#endif + +/* gteFLAG = 0; + + SS = psxRegs.CP2D.r[17] & 0xffff; SZ1 = (double)SS; + SS = psxRegs.CP2D.r[18] & 0xffff; SZ2 = (double)SS; + SS = psxRegs.CP2D.r[19] & 0xffff; SZ3 = (double)SS; + SS = psxRegs.CP2C.r[29] & 0xffff; ZSF3 = (double)SS/(double)4096; + + psxRegs.CP2D.r[24] = (signed long)float2int(EDETEC4(((SZ1+SZ2+SZ3)*ZSF3))); + psxRegs.CP2D.r[7] = (unsigned short)float2int(LimitC(((SZ1+SZ2+SZ3)*ZSF3),18)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + + gteFLAG = 0; + + /* NC: OLD + gteMAC0 = ((gteSZ1 + gteSZ2 + gteSZx) * (gteZSF3/4096.0f)); + + gteOTZ = limC((double)gteMAC0); + */ +/* gteMAC0 = ((gteSZ1 + gteSZ2 + gteSZx) * (gteZSF3)); + + gteOTZ = limC((double)(gteMAC0 >> 12));*/ + gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2) * (gteZSF3)) >> 12; + + gteOTZ = limC((double)gteMAC0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(7); + G_GD(24); + G_GC(31); + } +#endif +} + +void gteAVSZ4() { +// unsigned long SS; +// double SZ0,SZ1,SZ2,SZ3; +// double ZSF4; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_AVSZ4\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("AVSZ4", 6); + G_SD(16); + G_SD(17); + G_SD(18); + G_SD(19); + G_SC(29); + G_SC(30); + } +#endif + +/* gteFLAG = 0; + + SS = psxRegs.CP2D.r[16] & 0xffff; SZ0 = (double)SS; + SS = psxRegs.CP2D.r[17] & 0xffff; SZ1 = (double)SS; + SS = psxRegs.CP2D.r[18] & 0xffff; SZ2 = (double)SS; + SS = psxRegs.CP2D.r[19] & 0xffff; SZ3 = (double)SS; + SS = psxRegs.CP2C.r[30] & 0xffff; ZSF4 = (double)SS/(double)4096; + + psxRegs.CP2D.r[24] = (signed long)float2int(EDETEC4(((SZ0+SZ1+SZ2+SZ3)*ZSF4))); + psxRegs.CP2D.r[7] = (unsigned short)float2int(LimitC(((SZ0+SZ1+SZ2+SZ3)*ZSF4),18)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + /* NC: OLD + gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2 + gteSZx) * (gteZSF4/4096.0f)); + + gteOTZ = limC((double)gteMAC0); + */ +/* gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2 + gteSZx) * (gteZSF4)); + + gteOTZ = limC((double)(gteMAC0 >> 12)); +*/ + gteMAC0 = ((gteSZx + gteSZ0 + gteSZ1 + gteSZ2) * (gteZSF4))>> 12; + + gteOTZ = limC((double)gteMAC0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(7); + G_GD(24); + G_GC(31); + } +#endif +} + +void gteSQR() { + //double SSX0,SSY0,SSZ0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_SQR %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("SQR", 5); + G_SD(9); + G_SD(10); + G_SD(11); + } +#endif + +/* gteFLAG = 0; + + SSX0 = (double)gteIR1 * gteIR1; + SSY0 = (double)gteIR2 * gteIR2; + SSZ0 = (double)gteIR3 * gteIR3; + + if (psxRegs.code & 0x80000) { + SSX0 /= 4096.0; SSY0 /= 4096.0; SSZ0 /= 4096.0; + } + + gteMAC1 = (long)SSX0; + gteMAC2 = (long)SSY0; + gteMAC3 = (long)SSZ0; + + MAC2IR1(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1((gteIR1 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteIR2 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteIR3 * gteIR3) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteIR1 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR2 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR3 * gteIR3); + } + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + G_GD(25); + G_GD(26); + G_GD(27); + G_GC(31); + } +#endif +} +/* +#define GTE_NCCS(vn) { \ + RR0 = ((double)gteL11 * gteVX##vn + (double)gteL12 * gteVY##vn + (double)gteL13 * gteVZ##vn)/4096.0; \ + GG0 = ((double)gteL21 * gteVX##vn + (double)gteL22 * gteVY##vn + (double)gteL23 * gteVZ##vn)/4096.0; \ + BB0 = ((double)gteL31 * gteVX##vn + (double)gteL32 * gteVY##vn + (double)gteL33 * gteVZ##vn)/4096.0; \ + t1 = LimitAU(RR0,24); \ + t2 = LimitAU(GG0,23); \ + t3 = LimitAU(BB0,22); \ + \ + RR0 = (double)gteRBK + ((double)gteLR1 * t1 + (double)gteLR2 * t2 + (double)gteLR3 * t3)/4096.0; \ + GG0 = (double)gteGBK + ((double)gteLG1 * t1 + (double)gteLG2 * t2 + (double)gteLG3 * t3)/4096.0; \ + BB0 = (double)gteBBK + ((double)gteLB1 * t1 + (double)gteLB2 * t2 + (double)gteLB3 * t3)/4096.0; \ + t1 = LimitAU(RR0,24); \ + t2 = LimitAU(GG0,23); \ + t3 = LimitAU(BB0,22); \ + \ + RR0 = ((double)gteR * t1)/256.0; \ + GG0 = ((double)gteG * t2)/256.0; \ + BB0 = ((double)gteB * t3)/256.0; \ + \ + gteIR1 = (long)LimitAU(RR0,24); \ + gteIR2 = (long)LimitAU(GG0,23); \ + gteIR3 = (long)LimitAU(BB0,22); \ + \ + gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE; \ + gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)LimitB(RR0/16.0,21); \ + gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)LimitB(GG0/16.0,20); \ + gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)LimitB(BB0/16.0,19); \ + \ + gteMAC1 = (long)RR0; \ + gteMAC2 = (long)GG0; \ + gteMAC3 = (long)BB0; \ +} +*/ +/* +__forceinline double ncLIM1(double x) +{ + if(x > 8796093022207.0) + { + return 8796093022207.0; + } +} +*/ + + + +/* NC: OLD +#define GTE_NCCS(vn)\ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gte_RR0 = gteR*gte_RRLT;\ +gte_GG0 = gteG*gte_GGLT;\ +gte_BB0 = gteB*gte_BBLT;\ +gteIR1 = (long)limA1U(gte_RR0);\ +gteIR2 = (long)limA2U(gte_GG0);\ +gteIR3 = (long)limA3U(gte_BB0);\ +gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE;\ +gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)limB1(gte_RR0);\ +gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)limB2(gte_GG0);\ +gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)limB3(gte_BB0);\ +gteMAC1 = (long)gte_RR0;\ +gteMAC2 = (long)gte_GG0;\ +gteMAC3 = (long)gte_BB0;\ +*/ + +#define GTE_NCCS(vn)\ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gteMAC1 = (long)(gteR*gte_RRLT*16);\ +gteMAC2 = (long)(gteG*gte_GGLT*16);\ +gteMAC3 = (long)(gteB*gte_BBLT*16);\ +gteIR1 = (long)limA1U(gteMAC1);\ +gteIR2 = (long)limA2U(gteMAC2);\ +gteIR3 = (long)limA3U(gteMAC3);\ +gte_RR0 = gteMAC1>>4;\ +gte_GG0 = gteMAC2>>4;\ +gte_BB0 = gteMAC3>>4;\ +gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE;\ +gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)limB1(gte_RR0);\ +gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)limB2(gte_GG0);\ +gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)limB3(gte_BB0);\ + +void gteNCCS() { +// double RR0,GG0,BB0; +// double t1, t2, t3; + + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCCS\n"); +#endif + +/* + gteFLAG = 0; + + GTE_NCCS(0); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCCS", 17); + G_SD(0); + G_SD(1); + G_SD(6); + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif + + gteFLAG = 0; + + GTE_NCCS(0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + //G_GD(24); Doc must be wrong. PSX does not touch it. + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCCT() { +// double RR0,GG0,BB0; +// double t1, t2, t3; + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCCT\n"); +#endif + + + /*gteFLAG = 0; + + GTE_NCCS(0); + GTE_NCCS(1); + GTE_NCCS(2); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCCT", 39); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif + + gteFLAG = 0; + + GTE_NCCS(0); + GTE_NCCS(1); + GTE_NCCS(2); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + //G_GD(24); Doc must be wrong. PSX does not touch it. + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define GTE_NCDS(vn) \ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gte_RR0 = (gteR*gte_RRLT) + (gteIR0/4096.0f * limA1S(gteRFC/16.0f - (gteR*gte_RRLT)));\ +gte_GG0 = (gteG*gte_GGLT) + (gteIR0/4096.0f * limA2S(gteGFC/16.0f - (gteG*gte_GGLT)));\ +gte_BB0 = (gteB*gte_BBLT) + (gteIR0/4096.0f * limA3S(gteBFC/16.0f - (gteB*gte_BBLT)));\ +gteMAC1= (long)(gte_RR0 * 16.0f); gteIR1 = (long)limA1U(gte_RR0*16.0f);\ +gteMAC2= (long)(gte_GG0 * 16.0f); gteIR2 = (long)limA2U(gte_GG0*16.0f);\ +gteMAC3= (long)(gte_BB0 * 16.0f); gteIR3 = (long)limA3U(gte_BB0*16.0f);\ +gteRGB0 = gteRGB1; \ +gteRGB1 = gteRGB2; \ +gteR2 = limB1(gte_RR0); \ +gteG2 = limB2(gte_GG0); \ +gteB2 = limB3(gte_BB0); gteCODE2 = gteCODE; + +void gteNCDS() { +/* double tRLT,tRRLT; + double tGLT,tGGLT; + double tBLT,tBBLT; + double tRR0,tL1,tLL1; + double tGG0,tL2,tLL2; + double tBB0,tL3,tLL3; + unsigned long C,R,G,B; */ + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCDS\n"); +#endif + +/* gteFLAG = 0; + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX0/4096.0) + (gteL12/4096.0 * gteVY0/4096.0) + (gteL13/4096.0 * gteVZ0/4096.0); + tLL2 = (gteL21/4096.0 * gteVX0/4096.0) + (gteL22/4096.0 * gteVY0/4096.0) + (gteL23/4096.0 * gteVZ0/4096.0); + tLL3 = (gteL31/4096.0 * gteVX0/4096.0) + (gteL32/4096.0 * gteVY0/4096.0) + (gteL33/4096.0 * gteVZ0/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCDS", 19); + G_SD(0); + G_SD(1); + G_SD(6); + G_SD(8); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + GTE_NCDS(0); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCDT() { + /*double tRLT,tRRLT; + double tGLT,tGGLT; + double tBLT,tBBLT; + double tRR0,tL1,tLL1; + double tGG0,tL2,tLL2; + double tBB0,tL3,tLL3; + unsigned long C,R,G,B;*/ + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCDT\n"); +#endif + +/* gteFLAG = 0; + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX0/4096.0) + (gteL12/4096.0 * gteVY0/4096.0) + (gteL13/4096.0 * gteVZ0/4096.0); + tLL2 = (gteL21/4096.0 * gteVX0/4096.0) + (gteL22/4096.0 * gteVY0/4096.0) + (gteL23/4096.0 * gteVZ0/4096.0); + tLL3 = (gteL31/4096.0 * gteVX0/4096.0) + (gteL32/4096.0 * gteVY0/4096.0) + (gteL33/4096.0 * gteVZ0/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX1/4096.0) + (gteL12/4096.0 * gteVY1/4096.0) + (gteL13/4096.0 * gteVZ1/4096.0); + tLL2 = (gteL21/4096.0 * gteVX1/4096.0) + (gteL22/4096.0 * gteVY1/4096.0) + (gteL23/4096.0 * gteVZ1/4096.0); + tLL3 = (gteL31/4096.0 * gteVX1/4096.0) + (gteL32/4096.0 * gteVY1/4096.0) + (gteL33/4096.0 * gteVZ1/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX2/4096.0) + (gteL12/4096.0 * gteVY2/4096.0) + (gteL13/4096.0 * gteVZ2/4096.0); + tLL2 = (gteL21/4096.0 * gteVX2/4096.0) + (gteL22/4096.0 * gteVY2/4096.0) + (gteL23/4096.0 * gteVZ2/4096.0); + tLL3 = (gteL31/4096.0 * gteVX2/4096.0) + (gteL32/4096.0 * gteVY2/4096.0) + (gteL33/4096.0 * gteVZ2/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCDT", 44); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + G_SD(8); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + GTE_NCDS(0); + GTE_NCDS(1); + GTE_NCDS(2); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define gteD1 (*(short *)>eR11) +#define gteD2 (*(short *)>eR22) +#define gteD3 (*(short *)>eR33) + +void gteOP() { +// double SSX0=0,SSY0=0,SSZ0=0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_OP %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("OP", 6); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(0); + G_SC(2); + G_SC(4); + } +#endif +/* gteFLAG=0; + + switch (psxRegs.code & 0x1ffffff) { + case 0x178000C://op12 + SSX0 = EDETEC1((gteR22*(short)gteIR3 - gteR33*(short)gteIR2)/(double)4096); + SSY0 = EDETEC2((gteR33*(short)gteIR1 - gteR11*(short)gteIR3)/(double)4096); + SSZ0 = EDETEC3((gteR11*(short)gteIR2 - gteR22*(short)gteIR1)/(double)4096); + break; + case 0x170000C: + SSX0 = EDETEC1((gteR22*(short)gteIR3 - gteR33*(short)gteIR2)); + SSY0 = EDETEC2((gteR33*(short)gteIR1 - gteR11*(short)gteIR3)); + SSZ0 = EDETEC3((gteR11*(short)gteIR2 - gteR22*(short)gteIR1)); + break; + } + + gteMAC1 = (long)float2int(SSX0); + gteMAC2 = (long)float2int(SSY0); + gteMAC3 = (long)float2int(SSZ0); + + MAC2IR(); + + if (gteIR1<0) gteIR1=0; + if (gteIR2<0) gteIR2=0; + if (gteIR3<0) gteIR3=0; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1((gteD2 * gteIR3 - gteD3 * gteIR2) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteD3 * gteIR1 - gteD1 * gteIR3) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteD1 * gteIR2 - gteD2 * gteIR1) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteD2 * gteIR3 - gteD3 * gteIR2); + gteMAC2 = NC_OVERFLOW2(gteD3 * gteIR1 - gteD1 * gteIR3); + gteMAC3 = NC_OVERFLOW3(gteD1 * gteIR2 - gteD2 * gteIR1); + } + + /* NC: old + MAC2IR1(); + */ + MAC2IR(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteDCPL() { +// unsigned long C,R,G,B; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DCPL\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DCPL", 8); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif +/* R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + gteMAC1 = (signed long)((double)(R*gteIR1) + (double)(gteIR0*LimitAS(gteRFC-(double)(R*gteIR1),24))/4096.0); + gteMAC2 = (signed long)((double)(G*gteIR2) + (double)(gteIR0*LimitAS(gteGFC-(double)(G*gteIR2),23))/4096.0); + gteMAC3 = (signed long)((double)(B*gteIR3) + (double)(gteIR0*LimitAS(gteBFC-(double)(B*gteIR3),22))/4096.0); + + MAC2IR() + + R = (unsigned long)LimitB(gteMAC1,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(gteMAC2,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(gteMAC3,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR * gteIR1) / 256.0f + (gteIR0 * limA1S(gteRFC - ((gteR * gteIR1) / 256.0f))) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteG * gteIR1) / 256.0f + (gteIR0 * limA2S(gteGFC - ((gteG * gteIR1) / 256.0f))) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteB * gteIR1) / 256.0f + (gteIR0 * limA3S(gteBFC - ((gteB * gteIR1) / 256.0f))) / 4096.0f); + */ +/* gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)limA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>6; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)limA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>6; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)limA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>6;*/ + + gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)limA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>8; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)limA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>8; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)limA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>8; + + gteFLAG=0; + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteGPF() { +// double ipx, ipy, ipz; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_GPF %lx\n", psxRegs.code & 0x1ffffff); +#endif +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("GPF", 5); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + } +#endif +/* gteFLAG = 0; + + ipx = (double)((short)gteIR0) * ((short)gteIR1); + ipy = (double)((short)gteIR0) * ((short)gteIR2); + ipz = (double)((short)gteIR0) * ((short)gteIR3); + + // same as mvmva + if (psxRegs.code & 0x80000) { + ipx /= 4096.0; ipy /= 4096.0; ipz /= 4096.0; + } + + gteMAC1 = (long)ipx; + gteMAC2 = (long)ipy; + gteMAC3 = (long)ipz; + + gteIR1 = (long)LimitAS(ipx,24); + gteIR2 = (long)LimitAS(ipy,23); + gteIR3 = (long)LimitAS(ipz,22); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteC2 = gteCODE; + gteR2 = (unsigned char)LimitB(ipx,21); + gteG2 = (unsigned char)LimitB(ipy,20); + gteB2 = (unsigned char)LimitB(ipz,19);*/ + + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + gteMAC1 = NC_OVERFLOW1((gteIR0 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteIR0 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteIR0 * gteIR3) / 4096.0f); + } else { + gteMAC1 = NC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR0 * gteIR3); + } + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteGPL() { + // double IPX=0,IPY=0,IPZ=0; +// unsigned long C,R,G,B; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_GPL %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("GPL", 5); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SD(25); + G_SD(26); + G_SD(27); + } +#endif + +/* gteFLAG=0; + switch(psxRegs.code & 0x1ffffff) { + case 0x1A8003E: + IPX = EDETEC1((double)gteMAC1 + ((double)gteIR0*(double)gteIR1)/4096.0f); + IPY = EDETEC2((double)gteMAC2 + ((double)gteIR0*(double)gteIR2)/4096.0f); + IPZ = EDETEC3((double)gteMAC3 + ((double)gteIR0*(double)gteIR3)/4096.0f); + break; + + case 0x1A0003E: + IPX = EDETEC1((double)gteMAC1 + ((double)gteIR0*(double)gteIR1)); + IPY = EDETEC2((double)gteMAC2 + ((double)gteIR0*(double)gteIR2)); + IPZ = EDETEC3((double)gteMAC3 + ((double)gteIR0*(double)gteIR3)); + break; + } + gteIR1 = (short)float2int(LimitAS(IPX,24)); + gteIR2 = (short)float2int(LimitAS(IPY,23)); + gteIR3 = (short)float2int(LimitAS(IPZ,22)); + + gteMAC1 = (int)float2int(IPX); + gteMAC2 = (int)float2int(IPY); + gteMAC3 = (int)float2int(IPZ); + + C = gteRGB & 0xff000000; + R = float2int(ALIMIT(IPX,0,255)); + G = float2int(ALIMIT(IPY,0,255)); + B = float2int(ALIMIT(IPZ,0,255)); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = C|R|(G<<8)|(B<<16);*/ + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1)); + gteMAC2 = NC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2)); + gteMAC3 = NC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3)); + } + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +/* +#define GTE_DPCS() { \ + RR0 = (double)R + (gteIR0*LimitAS((double)(gteRFC - R),24))/4096.0; \ + GG0 = (double)G + (gteIR0*LimitAS((double)(gteGFC - G),23))/4096.0; \ + BB0 = (double)B + (gteIR0*LimitAS((double)(gteBFC - B),22))/4096.0; \ + \ + gteIR1 = (long)LimitAS(RR0,24); \ + gteIR2 = (long)LimitAS(GG0,23); \ + gteIR3 = (long)LimitAS(BB0,22); \ + \ + gteRGB0 = gteRGB1; \ + gteRGB1 = gteRGB2; \ + gteC2 = C; \ + gteR2 = (unsigned char)LimitB(RR0/16.0,21); \ + gteG2 = (unsigned char)LimitB(GG0/16.0,20); \ + gteB2 = (unsigned char)LimitB(BB0/16.0,19); \ + \ + gteMAC1 = (long)RR0; \ + gteMAC2 = (long)GG0; \ + gteMAC3 = (long)BB0; \ +} +*/ +void gteDPCS() { +// unsigned long C,R,G,B; +// double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DPCS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DPCS", 8); + G_SD(6); + G_SD(8); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + +/* gteFLAG = 0; + + C = gteCODE; + R = gteR * 16.0; + G = gteG * 16.0; + B = gteB * 16.0; + + GTE_DPCS(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR * 16.0f) + (gteIR0 * limA1S(gteRFC - (gteR * 16.0f))) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteG * 16.0f) + (gteIR0 * limA2S(gteGFC - (gteG * 16.0f))) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteB * 16.0f) + (gteIR0 * limA3S(gteBFC - (gteB * 16.0f))) / 4096.0f); + */ + gteMAC1 = (gteR<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR<<4)) ) >>12); + gteMAC2 = (gteG<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG<<4)) ) >>12); + gteMAC3 = (gteB<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB<<4)) ) >>12); + + gteFLAG = 0; + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteDPCT() { +// unsigned long C,R,G,B; +// double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DPCT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DPCT", 17); + G_SD(8); + + G_SD(20); + G_SD(21); + G_SD(22); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif +/* gteFLAG = 0; + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR0 * 16.0f) + gteIR0 * limA1S(gteRFC - (gteR0 * 16.0f))); + gteMAC2 = NC_OVERFLOW2((gteG0 * 16.0f) + gteIR0 * limA2S(gteGFC - (gteG0 * 16.0f))); + gteMAC3 = NC_OVERFLOW3((gteB0 * 16.0f) + gteIR0 * limA3S(gteBFC - (gteB0 * 16.0f))); + */ + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12); +// MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12); +// MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12); + gteFLAG = 0; + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +/* +#define GTE_NCS(vn) { \ + RR0 = ((double)gteVX##vn * gteL11 + (double)gteVY##vn * (double)gteL12 + (double)gteVZ##vn * gteL13) / 4096.0; \ + GG0 = ((double)gteVX##vn * gteL21 + (double)gteVY##vn * (double)gteL22 + (double)gteVZ##vn * gteL23) / 4096.0; \ + BB0 = ((double)gteVX##vn * gteL31 + (double)gteVY##vn * (double)gteL32 + (double)gteVZ##vn * gteL33) / 4096.0; \ + t1 = LimitAU(RR0, 24); \ + t2 = LimitAU(GG0, 23); \ + t3 = LimitAU(BB0, 22); \ + \ + RR0 = (double)gteRBK + ((double)gteLR1 * t1 + (double)gteLR2 * t2 + (double)gteLR3 * t3) / 4096.0; \ + GG0 = (double)gteGBK + ((double)gteLG1 * t1 + (double)gteLG2 * t2 + (double)gteLG3 * t3) / 4096.0; \ + BB0 = (double)gteBBK + ((double)gteLB1 * t1 + (double)gteLB2 * t2 + (double)gteLB3 * t3) / 4096.0; \ + t1 = LimitAU(RR0, 24); \ + t2 = LimitAU(GG0, 23); \ + t3 = LimitAU(BB0, 22); \ + \ + gteRGB0 = gteRGB1; gteRGB1 = gteRGB2; \ + gteR2 = (unsigned char)LimitB(RR0/16.0, 21); \ + gteG2 = (unsigned char)LimitB(GG0/16.0, 20); \ + gteB2 = (unsigned char)LimitB(BB0/16.0, 19); \ + gteCODE2=gteCODE0; \ +}*/ + +#define LOW(a) (((a) < 0) ? 0 : (a)) + +#define GTE_NCS(vn) \ +RR0 = LOW((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/4096.0f); \ +GG0 = LOW((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/4096.0f); \ +BB0 = LOW((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/4096.0f); \ +gteMAC1 = gteRBK + (gteLR1*RR0 + gteLR2*GG0 + gteLR3*BB0)/4096.0f; \ +gteMAC2 = gteGBK + (gteLG1*RR0 + gteLG2*GG0 + gteLG3*BB0)/4096.0f; \ +gteMAC3 = gteBBK + (gteLB1*RR0 + gteLB2*GG0 + gteLB3*BB0)/4096.0f; \ +gteRGB0 = gteRGB1; \ +gteRGB1 = gteRGB2; \ +gteR2 = limB1(gteMAC1 / 16.0f); \ +gteG2 = limB2(gteMAC2 / 16.0f); \ +gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + +void gteNCS() { + double RR0,GG0,BB0; +// double t1, t2, t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_NCS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCS", 14); + G_SD(0); + G_SD(1); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif +/* gteFLAG = 0; + + GTE_NCS(0); + + gteMAC1=(long)RR0; + gteMAC2=(long)GG0; + gteMAC3=(long)BB0; + + gteIR1=(long)t1; + gteIR2=(long)t2; + gteIR3=(long)t3; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + GTE_NCS(0); + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCT() { + double RR0,GG0,BB0; +// double t1, t2, t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_NCT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCT", 30); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif +/* + gteFLAG = 0; + +//V0 + GTE_NCS(0); +//V1 + GTE_NCS(1); +//V2 + GTE_NCS(2); + + gteMAC1=(long)RR0; + gteMAC2=(long)GG0; + gteMAC3=(long)BB0; + + gteIR1=(long)t1; + gteIR2=(long)t2; + gteIR3=(long)t3; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + GTE_NCS(0); + GTE_NCS(1); + GTE_NCS(2); + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteCC() { + double RR0,GG0,BB0; +// double t1,t2,t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_CC\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("CC", 11); + G_SD(6); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + } +#endif +/* gteFLAG = 0; + + RR0 = (double)gteRBK + ((double)gteLR1 * gteIR1 + (double)gteLR2 * gteIR2 + (double)gteLR3 * gteIR3) / 4096.0; + GG0 = (double)gteGBK + ((double)gteLG1 * gteIR1 + (double)gteLG2 * gteIR2 + (double)gteLG3 * gteIR3) / 4096.0; + BB0 = (double)gteBBK + ((double)gteLB1 * gteIR1 + (double)gteLB2 * gteIR2 + (double)gteLB3 * gteIR3) / 4096.0; + t1 = LimitAU(RR0, 24); + t2 = LimitAU(GG0, 23); + t3 = LimitAU(BB0, 22); + + RR0=((double)gteR * t1)/256.0; + GG0=((double)gteG * t2)/256.0; + BB0=((double)gteB * t3)/256.0; + gteIR1 = (long)LimitAU(RR0,24); + gteIR2 = (long)LimitAU(GG0,23); + gteIR3 = (long)LimitAU(BB0,22); + + gteCODE0=gteCODE1; gteCODE1=gteCODE2; + gteC2 = gteCODE0; + gteR2 = (unsigned char)LimitB(RR0/16.0, 21); + gteG2 = (unsigned char)LimitB(GG0/16.0, 20); + gteB2 = (unsigned char)LimitB(BB0/16.0, 19); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + RR0 = NC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 + gteLR2*gteIR2 + gteLR3*gteIR3) / 4096.0f); + GG0 = NC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 + gteLG2*gteIR2 + gteLG3*gteIR3) / 4096.0f); + BB0 = NC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 + gteLB2*gteIR2 + gteLB3*gteIR3) / 4096.0f); + + gteMAC1 = gteR * RR0 / 256.0f; + gteMAC2 = gteG * GG0 / 256.0f; + gteMAC3 = gteB * BB0 / 256.0f; + + MAC2IR1(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteINTPL() { //test opcode +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_INTP\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("INTPL", 8); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + /* NC: old + gteFLAG=0; + gteMAC1 = gteIR1 + gteIR0*limA1S(gteRFC-gteIR1); + gteMAC2 = gteIR2 + gteIR0*limA2S(gteGFC-gteIR2); + gteMAC3 = gteIR3 + gteIR0*limA3S(gteBFC-gteIR3); + //gteFLAG = 0; + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + */ + +/* gteFLAG=0; + gteMAC1 = gteIR1 + gteIR0*(gteRFC-gteIR1)/4096.0; + gteMAC2 = gteIR2 + gteIR0*(gteGFC-gteIR2)/4096.0; + gteMAC3 = gteIR3 + gteIR0*(gteBFC-gteIR3)/4096.0; + + //gteMAC3 = (int)((((psxRegs).CP2D).n).ir3+(((psxRegs).CP2D).n).ir0 * ((((psxRegs).CP2C).n).bfc-(((psxRegs).CP2D).n).ir3)/4096.0); + + if(gteMAC3 > gteIR1 && gteMAC3 > gteBFC) + { + gteMAC3 = gteMAC3; + } + //gteFLAG = 0;*/ + //NEW CODE + gteMAC1 = gteIR1 + ((gteIR0*(signed short)limA1S(gteRFC-gteIR1))>>12); + gteMAC2 = gteIR2 + ((gteIR0*(signed short)limA2S(gteGFC-gteIR2))>>12); + gteMAC3 = gteIR3 + ((gteIR0*(signed short)limA3S(gteBFC-gteIR3))>>12); + gteFLAG = 0; + + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteCDP() { //test opcode + double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_CDP\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("CDP", 13); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + + RR0 = NC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 +gteLR2*gteIR2 + gteLR3*gteIR3)); + GG0 = NC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 +gteLG2*gteIR2 + gteLG3*gteIR3)); + BB0 = NC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 +gteLB2*gteIR2 + gteLB3*gteIR3)); + gteMAC1 = gteR*RR0 + gteIR0*limA1S(gteRFC-gteR*RR0); + gteMAC2 = gteG*GG0 + gteIR0*limA2S(gteGFC-gteG*GG0); + gteMAC3 = gteB*BB0 + gteIR0*limA3S(gteBFC-gteB*BB0); + MAC2IR1(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} diff --git a/Gte.h b/Gte.h new file mode 100644 index 0000000000..eaffa88bea --- /dev/null +++ b/Gte.h @@ -0,0 +1,52 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GTE_H__ +#define __GTE_H__ + +void gteMFC2(); +void gteCFC2(); +void gteMTC2(); +void gteCTC2(); +void gteLWC2(); +void gteSWC2(); + +void gteRTPS(); +void gteOP(); +void gteNCLIP(); +void gteDPCS(); +void gteINTPL(); +void gteMVMVA(); +void gteNCDS(); +void gteNCDT(); +void gteCDP(); +void gteNCCS(); +void gteCC(); +void gteNCS(); +void gteNCT(); +void gteSQR(); +void gteDCPL(); +void gteDPCT(); +void gteAVSZ3(); +void gteAVSZ4(); +void gteRTPT(); +void gteGPF(); +void gteGPL(); +void gteNCCT(); + +#endif /* __GTE_H__ */ diff --git a/Hw.c b/Hw.c new file mode 100644 index 0000000000..48f31fbbfc --- /dev/null +++ b/Hw.c @@ -0,0 +1,2620 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include + +#include "Common.h" +#include "ir5900.h" +#include "VUmicro.h" +#include "PsxMem.h" +#include "IPU.h" + +#include + + +int hwInit() { + +#ifndef WIN32_VIRTUAL_MEM + psH = (u8*)_aligned_malloc(0x00010000, 16); + if (psH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } +#endif + + gsInit(); + vif0Init(); + vif1Init(); + vifDmaInit(); + sifInit(); + sprInit(); + ipuInit(); + + return 0; +} + +void hwShutdown() { +#ifndef WIN32_VIRTUAL_MEM + if (psH == NULL) return; + _aligned_free(psH); psH = NULL; +#endif + ipuShutdown(); +} + +void hwReset() { + +#ifdef WIN32_VIRTUAL_MEM + + memset(PS2MEM_HW+0x2000, 0, 0x0000e000); + psHu32(0xf520) = 0x1201; + psHu32(0xf260) = 0x1D000060; +#else + memset(psH, 0, 0x00010000); +#endif + // i guess this is kinda a version, it's used by some bioses + psHu32(0xf590) = 0x1201; + + gsReset(); + ipuReset(); +} + +u8 hwRead8(u32 mem) +{ + u8 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 8bit at %lx, ret %lx\n", mem, psHu8(mem)); +#endif + + switch (mem) { + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem); + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u8)ret; + } + + if (mem < 0x10010000) + { + ret = psHu8(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 8 at %x\n",mem); +#endif + break; + } + + return ret; +} + +int hwConstRead8(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + //psHu32(mem) &= ~0x4000; + return 0; + } + } + + if (mem < 0x10010000) + { + _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; +} + +u16 hwRead16(u32 mem) +{ + u16 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 16bit at %lx, ret %lx\n", mem, psHu16(mem)); +#endif + switch (mem) { + case 0x10000000: ret = (u16)rcntRcount(0); break; + case 0x10000010: ret = (u16)counters[0].mode; break; + case 0x10000020: ret = (u16)counters[0].target; break; + case 0x10000030: ret = (u16)counters[0].hold; break; + + case 0x10000800: ret = (u16)rcntRcount(1); break; + case 0x10000810: ret = (u16)counters[1].mode; break; + case 0x10000820: ret = (u16)counters[1].target; break; + case 0x10000830: ret = (u16)counters[1].hold; break; + + case 0x10001000: ret = (u16)rcntRcount(2); break; + case 0x10001010: ret = (u16)counters[2].mode; break; + case 0x10001020: ret = (u16)counters[2].target; break; + + case 0x10001800: ret = (u16)rcntRcount(3); break; + case 0x10001810: ret = (u16)counters[3].mode; break; + case 0x10001820: ret = (u16)counters[3].target; break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu16(mem) | 0x0102; + psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u16)ret; + } + if (mem < 0x10010000) { + ret = psHu16(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 16 at %x\n",mem); +#endif + break; + } + + return ret; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +static u32 s_regreads[3] = {0x010200000, 0xbfff0000, 0xF0000102}; +int hwConstRead16(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif + + switch (mem) { + case 0x10000000: + PUSH32I(0); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); + return 0; + case 0x10000020: + _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); + return 0; + case 0x10000030: + _eeReadConstMem16(x86reg, (u32)&counters[0].hold, sign); + return 0; + + case 0x10000800: + PUSH32I(1); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10000810: + _eeReadConstMem16(x86reg, (u32)&counters[1].mode, sign); + return 0; + + case 0x10000820: + _eeReadConstMem16(x86reg, (u32)&counters[1].target, sign); + return 0; + + case 0x10000830: + _eeReadConstMem16(x86reg, (u32)&counters[1].hold, sign); + return 0; + + case 0x10001000: + PUSH32I(2); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001010: + _eeReadConstMem16(x86reg, (u32)&counters[2].mode, sign); + return 0; + + case 0x10001020: + _eeReadConstMem16(x86reg, (u32)&counters[2].target, sign); + return 0; + + case 0x10001800: + PUSH32I(3); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001810: + _eeReadConstMem16(x86reg, (u32)&counters[3].mode, sign); + return 0; + + case 0x10001820: + _eeReadConstMem16(x86reg, (u32)&counters[3].target, sign); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff] - 2); + PORMtoR(x86reg&0xf, (u32)&s_regreads[0]); + PANDMtoR(x86reg&0xf, (u32)&s_regreads[1]); + } + else { + if( sign ) MOVSX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + else MOVZX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + + OR32ItoR(x86reg, 0x0102); + AND32ItoR(x86reg, ~0x4000); + } + return 0; + } + } + if (mem < 0x10010000) { + _eeReadConstMem16(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +static int b440; + +extern BOOL bExecBIOS; +static int b440table[] = { + 0, 31, 31, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0 }; + +#ifdef WIN32_VIRTUAL_MEM +__declspec(naked) void recCheckF440() +{ + __asm { + add b440, 1 + mov eax, b440 + sub eax, 3 + mov edx, 31 + + cmp eax, 27 + ja WriteVal + shl eax, 2 + mov edx, dword ptr [eax+b440table] + +WriteVal: + mov eax, PS2MEM_BASE_+0x1000f440 + mov dword ptr [eax], edx + ret + } +} + +void iMemRead32Check() +{ + // test if 0xf440 + if( bExecBIOS ) { + u8* ptempptr[2]; + CMP32ItoR(ECX, 0x1000f440); + ptempptr[0] = JNE8(0); + +// // increment and test +// INC32M((int)&b440); +// MOV32MtoR(EAX, (int)&b440); +// SUB32ItoR(EAX, 3); +// MOV32ItoR(EDX, 31); +// +// CMP32ItoR(EAX, 27); +// +// // look up table +// ptempptr[1] = JA8(0); +// SHL32ItoR(EAX, 2); +// ADD32ItoR(EAX, (int)b440table); +// MOV32RmtoR(EDX, EAX); +// +// x86SetJ8( ptempptr[1] ); +// +// MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + CALLFunc((u32)recCheckF440); + + x86SetJ8( ptempptr[0] ); + } +} + +#endif + +u32 hwRead32(u32 mem) { + u32 ret; + +#ifdef SPR_LOG + SPR_LOG("Hardware read 32bit at %lx, ret %lx\n", mem, psHu32(mem)); +#endif + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead32(mem); + } + + // gauntlen uses 0x1001xxxx + switch (mem) { + case 0x10000000: return (u16)rcntRcount(0); + case 0x10000010: return (u16)counters[0].mode; + case 0x10000020: return (u16)counters[0].target; + case 0x10000030: return (u16)counters[0].hold; + + case 0x10000800: return (u16)rcntRcount(1); + case 0x10000810: return (u16)counters[1].mode; + case 0x10000820: return (u16)counters[1].target; + case 0x10000830: return (u16)counters[1].hold; + + case 0x10001000: return (u16)rcntRcount(2); + case 0x10001010: return (u16)counters[2].mode; + case 0x10001020: return (u16)counters[2].target; + + case 0x10001800: return (u16)rcntRcount(3); + case 0x10001810: return (u16)counters[3].mode; + case 0x10001820: return (u16)counters[3].target; + +#ifdef PCSX2_DEVBUILD + case 0x1000A000: + ret = psHu32(mem);//dma2 chcr + HW_LOG("Hardware read DMA2_CHCR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A010: + ret = psHu32(mem);//dma2 madr + HW_LOG("Hardware read DMA2_MADR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A020: + ret = psHu32(mem);//dma2 qwc + HW_LOG("Hardware readDMA2_QWC 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A030: + ret = psHu32(mem);//dma2 taddr + HW_LOG("Hardware read DMA2_TADDR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A040: + ret = psHu32(mem);//dma2 asr0 + HW_LOG("Hardware read DMA2_ASR0 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A050: + ret = psHu32(mem);//dma2 asr1 + HW_LOG("Hardware read DMA2_ASR1 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A080: + ret = psHu32(mem);//dma2 saddr + HW_LOG("Hardware read DMA2_SADDR 32 at %lx, ret %lx\n", mem, ret); + break; + case 0x1000B400: // dma4 chcr + ret = ((DMACh *)&PS2MEM_HW[0xb400])->chcr; + SPR_LOG("Hardware read IPU1_CHCR 32 at %lx, ret %x\n", mem, ret); + break; + + case 0x1000e010: // DMAC_STAT + HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010)); + return psHu32(0xe010); + case 0x1000f000: // INTC_STAT +// HW_LOG("INTC_STAT Read 32bit %x\n", psHu32(0xf000)); + return psHu32(0xf000); + case 0x1000f010: // INTC_MASK + HW_LOG("INTC_MASK Read 32bit %x\n", psHu32(0xf010)); + return psHu32(0xf010); +#endif + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + ret = 0; + break; + + case 0x1000f440: + + b440++; + switch (b440) { + case 3: case 6: case 9: case 10: + case 13: case 14: + case 17: case 18: + case 21: case 22: + case 25: case 26: + case 29: case 30: + ret = 0; break; + default: + ret = 0x1f; break; + } + break; + + case 0x1000f520: // DMAC_ENABLER +#ifdef HW_LOG + HW_LOG("DMAC_ENABLER Read 32bit %lx\n", psHu32(0xf590)); +#endif + return psHu32(0xf590); + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + // SIF Control Registers + /*1D000020 (word) - EE -> IOP status flag ( set to 0x10000 always ready ) + 1D000030 (word) - IOP -> EE status flag + 1D000040 (word) - See psxMem.c ( Initially set to 0xF00042 and reset to + to this value if 0x20 is written ) + 1D000060 (word) - used to detect whether the SIF interface exists + read must be 0x1D000060, or the top 20 bits must be zero + */ + // note, any changes you make in here, also make on recMemRead32 + if(mem ==0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem) | 0xF0000102; + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); +//#ifdef HW_LOG +// SysPrintf("sif %x(%x) Read 32bit %x\n", mem, 0xbd000000 | (mem & 0xf0),ret); +//#endif } + break; + + } + else if (mem < 0x10010000) { + ret = psHu32(mem); + } + else { + SysPrintf("32bit HW read of address 0x%x\n", mem); + ret = 0; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 32 at %lx, ret %lx\n", mem, ret); +#endif + break; + } + + return ret; +} + +int hwConstRead32(u32 x86reg, u32 mem) +{ + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuConstRead32(x86reg, mem); + } + + switch (mem) { + case 0x10000000: + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem32(x86reg, (u32)&counters[0].mode); + return 0; + case 0x10000020: + _eeReadConstMem32(x86reg, (u32)&counters[0].target); + return 0; + case 0x10000030: + _eeReadConstMem32(x86reg, (u32)&counters[0].hold); + return 0; + + case 0x10000800: + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000810: + _eeReadConstMem32(x86reg, (u32)&counters[1].mode); + return 0; + case 0x10000820: + _eeReadConstMem32(x86reg, (u32)&counters[1].target); + return 0; + case 0x10000830: + _eeReadConstMem32(x86reg, (u32)&counters[1].hold); + return 0; + + case 0x10001000: + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10001010: + _eeReadConstMem32(x86reg, (u32)&counters[2].mode); + return 0; + case 0x10001020: + _eeReadConstMem32(x86reg, (u32)&counters[2].target); + return 0; + case 0x10001030: + _eeReadConstMem32(x86reg, (u32)&counters[2].hold); + return 0; + + case 0x10001800: + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10001810: + _eeReadConstMem32(x86reg, (u32)&counters[3].mode); + return 0; + case 0x10001820: + _eeReadConstMem32(x86reg, (u32)&counters[3].target); + return 0; + case 0x10001830: + _eeReadConstMem32(x86reg, (u32)&counters[3].hold); + return 0; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + + case 0x1000f440: + //iMemRead32Check(); + // increment and test + INC32M((int)&b440); + MOV32MtoR(EAX, (int)&b440); + SUB32ItoR(EAX, 3); + MOV32ItoR(EDX, 31); + + CMP32ItoR(EAX, 27); + + // look up table + j8Ptr[8] = JA8(0); + SHL32ItoR(EAX, 2); + ADD32ItoR(EAX, (int)b440table); + MOV32RmtoR(EDX, EAX); + + x86SetJ8( j8Ptr[8] ); + + MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + + if( IS_XMMREG(x86reg) ) SSE2_MOVD_R_to_XMM(x86reg&0xf, EDX); + else if( IS_MMXREG(x86reg) ) MOVD32RtoMMX(x86reg&0xf, EDX); + else MOV32RtoR(x86reg, EDX); + + return 0; + + case 0x1000f520: // DMAC_ENABLER + _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[0xf590]); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_XMMREG(x86reg) ) { + SSEX_MOVD_M32_to_XMM(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); + SSEX_POR_M128_to_XMM(x86reg&0xf, (u32)&s_regreads[2]); + } + else if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); + PORMtoR(x86reg&0xf, (u32)&s_regreads[2]); + } + else { + MOV32MtoR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + OR32ItoR(x86reg, 0xF0000102); + } + return 0; + } + } + + if (mem < 0x10010000) { + _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + } + else { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +u64 hwRead64(u32 mem) { + u64 ret; + + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead64(mem); + } + + switch (mem) { + default: + if (mem < 0x10010000) { + ret = psHu64(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 64 at %x\n",mem); +#endif + break; + } + + return ret; +} + +void hwConstRead64(u32 mem, int mmreg) { + if ((mem>=0x10002000) && (mem<0x10003000)) { + ipuConstRead64(mem, mmreg); + return; + } + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)PSM(mem)); + else { + MOVQMtoR(mmreg, (u32)PSM(mem)); + SetMMXstate(); + } +} + +void hwRead128(u32 mem, u64 *out) { + if (mem >= 0x10004000 && mem < 0x10008000) { + ReadFIFO(mem, out); return; + } + + if (mem < 0x10010000) { + out[0] = psHu64(mem); + out[1] = psHu64(mem+8); + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 128 at %x\n",mem); +#endif +} + +__declspec(align(16)) u32 s_TempFIFO[4]; +void hwConstRead128(u32 mem, int xmmreg) { + if (mem >= 0x10004000 && mem < 0x10008000) { + iFlushCall(0); + PUSH32I((u32)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((u32)ReadFIFO); + ADD32ItoR(ESP, 8); + _eeReadConstMem128( xmmreg, (u32)&s_TempFIFO[0]); + return; + } + + _eeReadConstMem128( xmmreg, (u32)PSM(mem)); +} + +// dark cloud2 uses it +#define DmaExec8(name, num) { \ + psHu8(mem) = (u8)value; \ + if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1)) { \ + /*SysPrintf("Running DMA 8 %x\n", psHu32(mem & ~0x1));*/ \ + dma##name(); \ + } \ +} + +// when writing imm +#define recDmaExecI8(name, num) { \ + MOV8ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 1 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec8(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI8(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem8((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 1); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +char sio_buffer[1024]; +static int sio_count; + +void hwWrite8(u32 mem, u8 value) { + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite8 to %x\n", mem); +#endif + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, value); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, value); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, value); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, value); break; + case 0x10001820: rcntWtarget(3, value); break; + + case 0x1000f180: + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +// SysPrintf("%c", value); + break; + + case 0x10008001: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 +#ifdef DMA_LOG + DMA_LOG("VIF1dma %lx\n", value); +#endif + DmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite8: GSdma %lx 0x%lx\n", cpuRegs.cycle, value); +#endif + DmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + psHu8(0xf592) = value; + psHu8(0xf522) = value; + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu8(mem) = value; + break; + case 0x40: + if(!(value & 0x100)) psHu32(mem) &= ~0x100; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + psHu8(mem) = value; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 8 at %x with value %x\n", mem, value); +#endif + break; + } +} + +static void PrintDebug(u8 value) +{ + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +} + +#define CONSTWRITE_CALLTIMER(name, index, bit) { \ + if( !IS_CONSTREG(mmreg) ) { \ + if( bit == 8 ) MOVZX32R8toR(mmreg&0xf, mmreg&0xf); \ + else if( bit == 16 ) MOVZX32R16toR(mmreg&0xf, mmreg&0xf); \ + } \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + PUSH32I(index); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 8); \ +} \ + +#define CONSTWRITE_TIMERS(bit) \ + case 0x10000000: CONSTWRITE_CALLTIMER(rcntWcount, 0, bit); break; \ + case 0x10000010: CONSTWRITE_CALLTIMER(rcntWmode, 0, bit); break; \ + case 0x10000020: CONSTWRITE_CALLTIMER(rcntWtarget, 0, bit); break; \ + case 0x10000030: CONSTWRITE_CALLTIMER(rcntWhold, 0, bit); break; \ + \ + case 0x10000800: CONSTWRITE_CALLTIMER(rcntWcount, 1, bit); break; \ + case 0x10000810: CONSTWRITE_CALLTIMER(rcntWmode, 1, bit); break; \ + case 0x10000820: CONSTWRITE_CALLTIMER(rcntWtarget, 1, bit); break; \ + case 0x10000830: CONSTWRITE_CALLTIMER(rcntWhold, 1, bit); break; \ + \ + case 0x10001000: CONSTWRITE_CALLTIMER(rcntWcount, 2, bit); break; \ + case 0x10001010: CONSTWRITE_CALLTIMER(rcntWmode, 2, bit); break; \ + case 0x10001020: CONSTWRITE_CALLTIMER(rcntWtarget, 2, bit); break; \ + \ + case 0x10001800: CONSTWRITE_CALLTIMER(rcntWcount, 3, bit); break; \ + case 0x10001810: CONSTWRITE_CALLTIMER(rcntWmode, 3, bit); break; \ + case 0x10001820: CONSTWRITE_CALLTIMER(rcntWtarget, 3, bit); break; \ + +void hwConstWrite8(u32 mem, int mmreg) +{ + switch (mem) { + CONSTWRITE_TIMERS(8) + + case 0x1000f180: + _recPushReg(mmreg); \ + iFlushCall(0); + CALLFunc((u32)PrintDebug); + ADD32ItoR(ESP, 4); + break; + + case 0x10008001: // dma0 - vif0 + recDmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 + recDmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif + recDmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU + recDmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU + recDmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 + recDmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 + recDmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR + recDmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR + recDmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf522], mmreg ); + _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf592], mmreg ); + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem8( (u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JNZ8(0); + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + x86SetJ8(j8Ptr[5]); + } + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem8((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem8((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } + + break; + } +} + +#define DmaExec16(name, num) { \ + psHu16(mem) = (u16)value; \ + if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + SysPrintf("16bit DMA Start\n"); \ + dma##name(); \ + } \ +} + +#define recDmaExecI16(name, num) { \ + MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec16(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI16(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwWrite16(u32 mem, u16 value) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite16 to %x\n", mem); +#endif + switch(mem) { + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec16(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec16(VIF1, 1); + break; + +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec16(GIF, 2); + break; +#ifdef HW_LOG + + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec16(IPU0, 3); + break; + +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec16(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec16(SIF0, 5); + break; + + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec16(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec16(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + psHu16(0xf592) = value; + psHu16(0xf522) = value; + break; + case 0x1000f130: + case 0x1000f132: + case 0x1000f410: + case 0x1000f412: + case 0x1000f430: + case 0x1000f432: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu16(mem) = value; + break; + case 0x20: + psHu16(mem) |= value; + break; + case 0x30: + psHu16(mem) &= ~value; + break; + case 0x40: + assert( (mem&2)==0); + if(!(value & 0x100)) psHu16(mem) &= ~0x100; + else psHu16(mem) |= 0x100; + break; + case 0x60: + psHu16(mem) = 0; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + +#ifndef WIN32_VIRTUAL_MEM + if (mem < 0x10010000) +#endif + { + psHu16(mem) = value; + } + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 16 at %x with value %x\n",mem,value); +#endif +} + +void hwConstWrite16(u32 mem, int mmreg) +{ + switch(mem&~3) { + case 0x10008000: // dma0 - vif0 + recDmaExec16(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec16(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec16(GIF, 2); + break; + case 0x1000b000: // dma3 - fromIPU + recDmaExec16(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec16(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec16(SIF0, 5); + break; + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 + recDmaExec16(SIF1, 6); + break; + case 0x1000c800: // dma7 - sif2 + recDmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR + recDmaExec16(SPR0, 8); + break; + case 0x1000d400: // dma9 - toSPR + recDmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem16((u32)&PS2MEM_HW[0xf522], mmreg); + _eeWriteConstMem16((u32)&PS2MEM_HW[0xf592], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem16OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + if( IS_CONSTREG(mmreg) ) { + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else { + NOT32R(mmreg&0xf); + AND16RtoM((u32)&PS2MEM_HW[mem&0xffff], mmreg&0xf); + } + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + } + else { + OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem16((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } +} + +#define DmaExec(name, num) { \ + /* why not allowing tags on sif0/sif2? */ \ + if(mem!= 0x1000c000/* && mem != 0x1000c400*/ && mem != 0x1000c800) \ + psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value; \ + else \ + psHu32(mem) = (u32)value; \ + if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + dma##name(); \ + } \ +} + +// when writing an Imm +#define recDmaExecI(name, num) { \ + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]; \ + if(mem!= 0x1000c000 && mem != 0x1000c800) MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ + else MOV32ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ + if( c & 0x100 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + if(mem!= 0x1000c000 && mem != 0x1000c800) { \ + if( IS_XMMREG(mmreg) || IS_MMXREG(mmreg) ) { \ + MOV16RtoM((u32)&PS2MEM_HW[(mem) & 0xffff], EAX); \ + } \ + else { \ + _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + } \ + } \ + else _eeWriteConstMem32((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST16ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST32ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwWrite32(u32 mem, u32 value) { + int i; + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuWrite32(mem,value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, value); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, value); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, value); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, value); break; + case 0x10001820: rcntWtarget(3, value); break; + + case GIF_CTRL: + //SysPrintf("GIF_CTRL write %x\n", value); + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + return; + + case GIF_MODE: + // need to set GIF_MODE (hamster ball) + psHu32(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + SysPrintf("Gifstat write value = %x\n", value); + return; + + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec(VIF1, 1); + break; +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; +#ifdef HW_LOG + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec(IPU0, 3); + break; +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec(SPR1, 9); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 32bit %x\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 32bit %x\n", value); +#endif + psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 + value = value >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (value & (1<=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuConstWrite32(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x10000000: CONSTWRITE_CALLTIMER32(rcntWcount, 0, bit); break; + case 0x10000010: CONSTWRITE_CALLTIMER32(rcntWmode, 0, bit); break; + case 0x10000020: CONSTWRITE_CALLTIMER32(rcntWtarget, 0, bit); break; + case 0x10000030: CONSTWRITE_CALLTIMER32(rcntWhold, 0, bit); break; + + case 0x10000800: CONSTWRITE_CALLTIMER32(rcntWcount, 1, bit); break; + case 0x10000810: CONSTWRITE_CALLTIMER32(rcntWmode, 1, bit); break; + case 0x10000820: CONSTWRITE_CALLTIMER32(rcntWtarget, 1, bit); break; + case 0x10000830: CONSTWRITE_CALLTIMER32(rcntWhold, 1, bit); break; + + case 0x10001000: CONSTWRITE_CALLTIMER32(rcntWcount, 2, bit); break; + case 0x10001010: CONSTWRITE_CALLTIMER32(rcntWmode, 2, bit); break; + case 0x10001020: CONSTWRITE_CALLTIMER32(rcntWtarget, 2, bit); break; + + case 0x10001800: CONSTWRITE_CALLTIMER32(rcntWcount, 3, bit); break; + case 0x10001810: CONSTWRITE_CALLTIMER32(rcntWmode, 3, bit); break; + case 0x10001820: CONSTWRITE_CALLTIMER32(rcntWtarget, 3, bit); break; + + case GIF_CTRL: + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((u32)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + return; + + case GIF_STAT: // stat is readonly + return; + + case 0x10008000: // dma0 - vif0 + recDmaExec(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000b000: // dma3 - fromIPU + recDmaExec(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 + recDmaExec(SIF1, 6); + break; + + case 0x1000c800: // dma7 - sif2 + recDmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR + recDmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR + recDmaExec(SPR1, 9); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((u32)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((u32)&PS2MEM_HW[0xf000], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + return; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + else { + OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST32ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + MOV32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem32((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + break; + } +} + +void hwWrite64(u32 mem, u64 value) { + u32 val32; + int i; + + if ((mem>=0x10002000) && (mem<=0x10002030)) { + ipuWrite64(mem, value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case GIF_CTRL: +#ifdef PCSX2_DEVBUILD + SysPrintf("GIF_CTRL write 64\n", value); +#endif + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + + return; + + case GIF_MODE: + psHu64(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 64bit %x\n", value); + psHu64(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 64bit %x\n", value); +#endif + val32 = (u32)value; + psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1 + val32 = val32 >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (val32 & (1<=0x10002000) && (mem<=0x10002030)) { + ipuConstWrite64(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case GIF_CTRL: + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((u32)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((u32)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + + break; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + + _eeWriteConstMem64((u32)PSM(mem), mmreg); + break; + } +} + +void hwWrite128(u32 mem, u64 *value) { + if (mem >= 0x10004000 && mem < 0x10008000) { + WriteFIFO(mem, value); return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + psHu32(0xf590) = *(u32*)value; + psHu32(0xf520) = *(u32*)value; + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status); +#endif + break; + } +} + +void hwConstWrite128(u32 mem, int mmreg) +{ + if (mem >= 0x10004000 && mem < 0x10008000) { + _eeWriteConstMem128((u32)&s_TempFIFO[0], mmreg); + iFlushCall(0); + PUSH32I((u32)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((u32)WriteFIFO); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + +#ifdef WIN32_VIRTUAL_MEM + _eeWriteConstMem128( PS2MEM_BASE_+mem, mmreg); +#else + if (mem < 0x10010000) + _eeWriteConstMem128((u32)&PS2MEM_HW[mem&0xffff], mmreg); +#endif + break; + } +} + +int intcInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu32(INTC_STAT)) == 0) { + SysPrintf("*PCSX2*: intcInterrupt already cleared\n"); + return 1; + } + if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("intcInterrupt %x\n", psHu32(INTC_STAT) & psHu32(INTC_MASK)); +#endif + if(psHu32(INTC_STAT) & 0x2){ + counters[0].hold = rcntRcount(0); + counters[1].hold = rcntRcount(1); + } + + cpuException(0x400, cpuRegs.branch); + + return 1; +} + +int dmacTestInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + return 1; +} + +int dmacInterrupt() +{ +if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("dmacInterrupt %x\n", (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)); +#endif + + cpuException(0x800, cpuRegs.branch); + return 1; +} + +void hwIntcIrq(int n) { + //if( psHu32(INTC_MASK) & (1< (maddr+msize)) { +// int s1 = (maddr+msize) - addr; +// int s2 = size - s1; +// +// /* it does, so first copy 's1' bytes from 'addr' to 'data' */ +// src = PSM(addr); +// if (src == NULL) return -1; +// memcpy_amd(data, src, s1); +// +// /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ +// src = PSM(maddr); +// if (src == NULL) return -1; +// memcpy(&data[s1], src, s2); +// } else { +// //u32 * tempptr, * tempptr2; +// /* it doesn't, so just copy 'size' bytes from 'addr' to 'data' */ +// src = PSM(addr); +// if (src == NULL) return -1; +// //tempptr = (u32*)src; +// //tempptr2 = (u32*)data; +// +// memcpy(data, src, size); +// } +// +// return 0; +//} + +/* Write 'size' bytes to memory address 'addr' from 'data'. */ +int hwMFIFOWrite(u32 addr, u8 *data, int size) { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u8 *dst; + + addr = psHu32(DMAC_RBOR) + (addr & psHu32(DMAC_RBSR)); + /* Check if the transfer should wrap around the ring buffer */ + if ((addr+size) > (maddr+msize)) { + int s1 = (maddr+msize) - addr; + int s2 = size - s1; + + /* it does, so first copy 's1' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, s1/4); + memcpy(dst, data, s1); + + /* and second copy 's2' bytes from '&data[s1]' to 'maddr' */ + dst = PSM(maddr); + if (dst == NULL) return -1; + Cpu->Clear(maddr, s2/4); + memcpy(dst, &data[s1], s2); + } else { + //u32 * tempptr, * tempptr2; + + /* it doesn't, so just copy 'size' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, size/4); + memcpy_amd(dst, data, size); + } + + return 0; +} + + +int hwDmacSrcChainWithStack(DMACh *dma, int id) { + u32 temp,finalAddress; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + //dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 5: // Call - Transfer QWC following the tag, save succeeding tag + temp = dma->madr; //Temporarily Store ADDR + finalAddress = dma->tadr + 16 + (dma->qwc << 4); //Store Address of Succeeding tag + + if (dma->asr0 == 0) //Check if ASR0 is empty + dma->asr0 = finalAddress; //If yes store Succeeding tag + else + dma->asr1 = finalAddress; //If no store Succeeding tag in ASR1 + + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + dma->tadr = temp; //Set TADR to temporarily stored ADDR + return 0; + + case 6: // Ret - Transfer QWC following the tag, load next tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + if (dma->asr1 != 0) { //If ASR1 is NOT equal to 0 (Contains address) + dma->tadr = dma->asr1; //Read ASR1 as next tag + dma->asr1 = 0; //Clear ASR1 + } else { //If ASR1 is empty (No address held) + if(dma->asr0 != 0) { //Check if ASR0 is NOT equal to 0 (Contains address) + dma->tadr = dma->asr0; //Read ASR0 as next tag + dma->asr0 = 0; //Clear ASR0 + } else { //Else if ASR1 and ASR0 are empty + dma->tadr = 0; //Clear tag address + return 1; //End Transfer + } + } + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //comment out tadr fixes lemans + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} + +int hwDmacSrcChain(DMACh *dma, int id) { + u32 temp; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + //dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} diff --git a/Hw.h b/Hw.h new file mode 100644 index 0000000000..0f5f03244a --- /dev/null +++ b/Hw.h @@ -0,0 +1,400 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __HW_H__ +#define __HW_H__ + +//#include "Common.h" +#include "PS2Etypes.h" +#include + +#ifndef WIN32_VIRTUAL_MEM +u8 *psH; // hw mem +u16 *psHW; +u32 *psHL; +u64 *psHD; +#endif + +#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff]) + +extern u32 g_nextBranchCycle; + +#define INT(n, ecycle) { \ + g_nextBranchCycle = min(g_nextBranchCycle, cpuRegs.cycle+ecycle); \ + cpuRegs.interrupt|= 1 << n; \ + cpuRegs.sCycle[n] = cpuRegs.cycle; \ + cpuRegs.eCycle[n] = ecycle; \ +} + +// VIF0 -- 0x10004000 -- psH[0x4000] +// VIF1 -- 0x10005000 -- psH[0x5000] +// GIF -- 0x10006000 -- psH[0x6000] +// IPUout -- 0x10007000 -- psH[0x7000] +// IPUin -- 0x10007010 -- psH[0x7010] + +void ReadFIFO(u32 mem, u64 *out); +void ConstReadFIFO(u32 mem); + +void WriteFIFO(u32 mem, u64 *value); +void ConstWriteFIFO(u32 mem); + + +// +// --- DMA --- +// + +typedef struct { + u32 chcr; + u32 null0[3]; + u32 madr; + u32 null1[3]; + u16 qwc; u16 pad; + u32 null2[3]; + u32 tadr; + u32 null3[3]; + u32 asr0; + u32 null4[3]; + u32 asr1; + u32 null5[11]; + u32 sadr; +} DMACh; + +int sifenabled[2]; + +// HW defines + +#define RCNT0_COUNT 0x10000000 +#define RCNT0_MODE 0x10000010 +#define RCNT0_TARGET 0x10000020 +#define RCNT0_HOLD 0x10000030 + +#define RCNT1_COUNT 0x10000800 +#define RCNT1_MODE 0x10000810 +#define RCNT1_TARGET 0x10000820 +#define RCNT1_HOLD 0x10000830 + +#define RCNT2_COUNT 0x10001000 +#define RCNT2_MODE 0x10001010 +#define RCNT2_TARGET 0x10001020 + +#define RCNT3_COUNT 0x10001800 +#define RCNT3_MODE 0x10001810 +#define RCNT3_TARGET 0x10001820 + +#define IPU_CMD 0x10002000 +#define IPU_CTRL 0x10002010 +#define IPU_BP 0x10002020 +#define IPU_TOP 0x10002030 + +#define GIF_CTRL 0x10003000 +#define GIF_MODE 0x10003010 +#define GIF_STAT 0x10003020 +#define GIF_TAG0 0x10003040 +#define GIF_TAG1 0x10003050 +#define GIF_TAG2 0x10003060 +#define GIF_TAG3 0x10003070 +#define GIF_CNT 0x10003080 +#define GIF_P3CNT 0x10003090 +#define GIF_P3TAG 0x100030A0 + +#define GIF_FIFO 0x10006000 + +#define IPUout_FIFO 0x10007000 +#define IPUin_FIFO 0x10007010 + +//VIF0 +#define D0_CHCR 0x10008000 +#define D0_MADR 0x10008010 +#define D0_QWC 0x10008020 + +//VIF1 +#define D1_CHCR 0x10009000 +#define D1_MADR 0x10009010 +#define D1_QWC 0x10009020 +#define D1_TADR 0x10009030 + +//GS +#define D2_CHCR 0x1000A000 +#define D2_MADR 0x1000A010 +#define D2_QWC 0x1000A020 +#define D2_TADR 0x1000A030 + +//fromIPU +#define D3_CHCR 0x1000B000 +#define D3_MADR 0x1000B010 +#define D3_QWC 0x1000B020 + +//toIPU +#define D4_CHCR 0x1000B400 +#define D4_MADR 0x1000B410 +#define D4_QWC 0x1000B420 +#define D4_TADR 0x1000B430 + +//SIF0 +#define D5_CHCR 0x1000C000 +#define D5_MADR 0x1000C010 +#define D5_QWC 0x1000C020 + +//SIF1 +#define D6_CHCR 0x1000C400 +#define D6_MADR 0x1000C410 +#define D6_QWC 0x1000C420 + +//SIF2 +#define D7_CHCR 0x1000C800 +#define D7_MADR 0x1000C810 +#define D7_QWC 0x1000C820 + +//fromSPR +#define D8_CHCR 0x1000D000 +#define D8_MADR 0x1000D010 +#define D8_QWC 0x1000D020 +#define D8_SADR 0x1000D080 + + +#define DMAC_CTRL 0x1000E000 +#define DMAC_STAT 0x1000E010 +#define DMAC_PCR 0x1000E020 +#define DMAC_SQWC 0x1000E030 +#define DMAC_RBSR 0x1000E040 +#define DMAC_RBOR 0x1000E050 +#define DMAC_STADR 0x1000E060 + +#define INTC_STAT 0x1000F000 +#define INTC_MASK 0x1000F010 + +#define SBUS_F220 0x1000F220 +#define SBUS_SMFLG 0x1000F230 +#define SBUS_F240 0x1000F240 + +#define DMAC_ENABLER 0x1000F520 +#define DMAC_ENABLEW 0x1000F590 + +#define SBFLG_IOPALIVE 0x10000 +#define SBFLG_IOPSYNC 0x40000 + +#define GS_PMODE 0x12000000 +#define GS_SMODE1 0x12000010 +#define GS_SMODE2 0x12000020 +#define GS_SRFSH 0x12000030 +#define GS_SYNCH1 0x12000040 +#define GS_SYNCH2 0x12000050 +#define GS_SYNCV 0x12000060 +#define GS_DISPFB1 0x12000070 +#define GS_DISPLAY1 0x12000080 +#define GS_DISPFB2 0x12000090 +#define GS_DISPLAY2 0x120000A0 +#define GS_EXTBUF 0x120000B0 +#define GS_EXTDATA 0x120000C0 +#define GS_EXTWRITE 0x120000D0 +#define GS_BGCOLOR 0x120000E0 +#define GS_CSR 0x12001000 +#define GS_IMR 0x12001010 +#define GS_BUSDIR 0x12001040 +#define GS_SIGLBLID 0x12001080 + +#define INTC_GS 0 +#define INTC_SBUS 1 +#define INTC_VBLANK_S 2 +#define INTC_VBLANK_E 3 +#define INTC_VIF0 4 +#define INTC_VIF1 5 +#define INTC_VU0 6 +#define INTC_VU1 7 +#define INTC_IPU 8 +#define INTC_TIM0 9 +#define INTC_TIM1 10 +#define INTC_TIM2 11 +#define INTC_TIM3 12 + +#define DMAC_VIF0 0 +#define DMAC_VIF1 1 +#define DMAC_GIF 2 +#define DMAC_FROM_IPU 3 +#define DMAC_TO_IPU 4 +#define DMAC_SIF0 5 +#define DMAC_SIF1 6 +#define DMAC_SIF2 7 +#define DMAC_FROM_SPR 8 +#define DMAC_TO_SPR 9 +#define DMAC_ERROR 15 + +#define VIF0_STAT_VPS_W (1) +#define VIF0_STAT_VPS_D (2) +#define VIF0_STAT_VPS_T (3) +#define VIF0_STAT_VPS (3) +#define VIF0_STAT_VEW (1<<2) +#define VIF0_STAT_MRK (1<<6) +#define VIF0_STAT_DBF (1<<7) +#define VIF0_STAT_VSS (1<<8) +#define VIF0_STAT_VFS (1<<9) +#define VIF0_STAT_VIS (1<<10) +#define VIF0_STAT_INT (1<<11) +#define VIF0_STAT_ER0 (1<<12) +#define VIF0_STAT_ER1 (1<<13) + +#define VIF1_STAT_VPS_W (1) +#define VIF1_STAT_VPS_D (2) +#define VIF1_STAT_VPS_T (3) +#define VIF1_STAT_VPS (3) +#define VIF1_STAT_VEW (1<<2) +#define VIF1_STAT_VGW (1<<3) +#define VIF1_STAT_MRK (1<<6) +#define VIF1_STAT_DBF (1<<7) +#define VIF1_STAT_VSS (1<<8) +#define VIF1_STAT_VFS (1<<9) +#define VIF1_STAT_VIS (1<<10) +#define VIF1_STAT_INT (1<<11) +#define VIF1_STAT_ER0 (1<<12) +#define VIF1_STAT_ER1 (1<<13) +#define VIF1_STAT_FDR (1<<23) + +//DMA interrupts & masks +#define BEISintr (0x8000) +#define VIF0intr (0x10001) +#define VIF1intr (0x20002) +#define GIFintr (0x40004) +#define IPU0intr (0x80008) +#define IPU1intr (0x100010) +#define SIF0intr (0x200020) +#define SIF1intr (0x400040) +#define SIF2intr (0x800080) +#define SPR0intr (0x1000100) +#define SPR1intr (0x2000200) +#define SISintr (0x20002000) +#define MEISintr (0x40004000) + +#define DMAend(dma, num) { \ + dma->chcr &= ~0x100; \ + psHu32(DMAC_STAT)|= 1<>12 ].aPFNs == NULL ) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", mem); + return NULL; + } +#endif + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); + return p; +} + +#else + +__forceinline void *dmaGetAddr(u32 addr) { + u8 *ptr; + +/*#ifdef DMA_LOG + if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x\n", addr); } +#endif*/ + if (addr & 0x80000000) { // teh sux why the f00k 0xE0000000 + return (void*)&psS[addr & 0x3ff0]; + } + + ptr = (u8*)memLUTR[addr >> 12]; + if (ptr == NULL) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", addr); + return NULL; + } + return (void*)(ptr + (addr & 0xff0)); +} + +#endif + +int hwInit(); +void hwReset(); +void hwShutdown(); + +// hw read functions +u8 hwRead8 (u32 mem); +int hwConstRead8 (u32 x86reg, u32 mem, u32 sign); + +u16 hwRead16(u32 mem); +int hwConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 hwRead32(u32 mem); +int hwConstRead32(u32 x86reg, u32 mem); + +u64 hwRead64(u32 mem); +void hwConstRead64(u32 mem, int mmreg); + +void hwRead128(u32 mem, u64 *out); +void hwConstRead128(u32 mem, int xmmreg); + +// hw write functions +void hwWrite8 (u32 mem, u8 value); +void hwConstWrite8 (u32 mem, int mmreg); + +void hwWrite16(u32 mem, u16 value); +void hwConstWrite16(u32 mem, int mmreg); + +void hwWrite32(u32 mem, u32 value); +void hwConstWrite32(u32 mem, int mmreg); + +void hwWrite64(u32 mem, u64 value); +void hwConstWrite64(u32 mem, int mmreg); + +void hwWrite128(u32 mem, u64 *value); +void hwConstWrite128(u32 mem, int xmmreg); + +void hwIntcIrq(int n); +void hwDmacIrq(int n); + +int hwMFIFORead(u32 addr, u8 *data, int size); +int hwMFIFOWrite(u32 addr, u8 *data, int size); + +int hwDmacSrcChainWithStack(DMACh *dma, int id); +int hwDmacSrcChain(DMACh *dma, int id); + +int intcInterrupt(); +int dmacInterrupt(); + +#endif /* __HW_H__ */ diff --git a/IPU/IPU.c b/IPU/IPU.c new file mode 100644 index 0000000000..4915cd7f16 --- /dev/null +++ b/IPU/IPU.c @@ -0,0 +1,1865 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "IPU.h" +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +#include +#include + +#include +#include + +#include "ir5900.h" +#include "pcl.h" + +#ifdef __WIN32__ +#define FASTCALL __fastcall +#else +#define FASTCALL +#endif + +#ifndef WIN32_VIRTUAL_MEM +IPUregisters g_ipuRegsReal; +#endif + +#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000]) +#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400]) + +#define IPU_DMA_GIFSTALL 1 +#define IPU_DMA_TIE0 2 +#define IPU_DMA_TIE1 4 +#define IPU_DMA_ACTV1 8 +#define IPU_DMA_DOTIE1 16 +#define IPU_DMA_FIREINT0 32 +#define IPU_DMA_FIREINT1 64 + +static int g_nDMATransfer = 0; +int g_nIPU0Data = 0; // data left to transfer +u8* g_pIPU0Pointer = NULL; +int g_nCmdPos[2] = {0}, g_nCmdIndex = 0; +static int ipuCurCmd = 0xffffffff; + +// returns number of qw read +int fifo_wread(void *value, int size); +int fifo_wread1(void *value); +int fifo_wwrite(u32* pMem, int size); +void fifo_wclear(); + +static int readwpos = 0, writewpos = 0; +__declspec(align(16)) u32 fifo_input[32]; + +void ReorderBitstream(); +u8 FillInternalBuffer(u32 * pointer, u32 advance); + +// the BP doesn't advance and returns -1 if there is no data to be read +tIPU_BP g_BP; +static coroutine_t s_routine; // used for executing BDEC/IDEC +static int s_RoutineDone = 0; +static u32 s_tempstack[0x1000]; // 16k + +void IPUCMD_WRITE(u32 val); +void IPUWorker(); +int IPU0dma(const void* pMem, int size); +int IPU1dma(); + +#define BigEndian _byteswap_ulong +//__forceinline u32 FASTCALL BigEndian(u32 a){ +// return ((((a >> 24) & 0xFF) << 0) + (((a >> 16) & 0xFF) << 8) + +// (((a >> 8) & 0xFF) << 16) + (((a >> 0) & 0xFF) << 24)); +//} + +// Color conversion stuff +char convert_data_buffer[0x1C]; +convert_init_t convert_init={convert_data_buffer, 0x1C}; +convert_t *convert; + +// Quantization matrix +static u8 niq[64], //non-intraquant matrix + iq[64]; //intraquant matrix +u16 vqclut[16]; //clut conversion table +static u8 s_thresh[2]; //thresholds for color conversions +int coded_block_pattern=0; +__declspec(align(16)) struct macroblock_8 mb8; +__declspec(align(16)) struct macroblock_16 mb16; +__declspec(align(16)) struct macroblock_rgb32 rgb32; +__declspec(align(16)) struct macroblock_rgb16 rgb16; + +u8 indx4[16*16/2]; +u32 mpeg2_inited; //mpeg2_idct_init() must be called only once +u8 PCT[]={'r', 'I', 'P', 'B', 'D', '-', '-', '-'}; +decoder_t g_decoder; //static, only to place it in bss +decoder_t tempdec; + +extern u8 mpeg2_scan_norm[64]; +extern u8 mpeg2_scan_alt[64]; + +__declspec(align(16)) u8 _readbits[80]; //local buffer (ring buffer) +u8* readbits = _readbits; // always can decrement by one 1qw + +#define SATURATE_4BITS(val) ((val)>15 ? 15 : (val)) + +void IPUProcessInterrupt() +{ + if( ipuRegs->ctrl.BUSY ) { + IPUWorker(); + } +} + +///////////////////////////////////////////////////////// +// Register accesses (run on EE thread) +int ipuInit() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + memset(&g_BP, 0, sizeof(g_BP)); + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + return 0; +} + +void ipuReset() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + g_nDMATransfer = 0; +} + +void ipuShutdown() +{ +} + +int ipuFreeze(gzFile f, int Mode) { + IPUProcessInterrupt(); + + gzfreeze(ipuRegs, sizeof(IPUregisters)); + gzfreeze(&g_nDMATransfer, sizeof(g_nDMATransfer)); + gzfreeze(&readwpos, sizeof(readwpos)); + gzfreeze(&writewpos, sizeof(writewpos)); + gzfreeze(fifo_input, sizeof(fifo_input)); + gzfreeze(&g_BP, sizeof(g_BP)); + gzfreeze(niq, sizeof(niq)); + gzfreeze(iq, sizeof(niq)); + gzfreeze(vqclut, sizeof(vqclut)); + gzfreeze(s_thresh, sizeof(s_thresh)); + gzfreeze(&coded_block_pattern, sizeof(coded_block_pattern)); + gzfreeze(&g_decoder, sizeof(g_decoder)); + gzfreeze(mpeg2_scan_norm, sizeof(mpeg2_scan_norm)); + gzfreeze(mpeg2_scan_alt, sizeof(mpeg2_scan_alt)); + gzfreeze(g_nCmdPos, sizeof(g_nCmdPos)); + gzfreeze(&g_nCmdIndex, sizeof(g_nCmdIndex)); + gzfreeze(&ipuCurCmd, sizeof(ipuCurCmd)); + + gzfreeze(_readbits, sizeof(_readbits)); + + if( Mode == 0 ) { + int temp = readbits-_readbits; + gzfreeze(&temp, sizeof(temp)); + } + else { + int temp; + gzfreeze(&temp, sizeof(temp)); + readbits = _readbits; + } + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + + return 0; +} + +BOOL ipuCanFreeze() +{ + return ipuCurCmd == 0xffffffff; +} + +u32 ipuRead32(u32 mem) +{ + IPUProcessInterrupt(); + + switch (mem){ + + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl.IFC = g_BP.IFC; + ipuRegs->ctrl.OFC = min(g_nIPU0Data, 8); // check if transfering to ipu0 + ipuRegs->ctrl.CBP = coded_block_pattern; + +#ifdef IPU_LOG + if( !ipuRegs->ctrl.BUSY ) { + IPU_LOG("Ipu read32: IPU_CTRL=0x%08X %x\n", ipuRegs->ctrl._u32, cpuRegs.pc); + } +#endif + return ipuRegs->ctrl._u32; + + case 0x10002020: // IPU_BP + + ipuRegs->ipubp = g_BP.BP & 0x7f; + ipuRegs->ipubp |= g_BP.IFC<<8; + ipuRegs->ipubp |= (g_BP.FP+g_BP.bufferhasnew) << 16; + +#ifdef IPU_LOG + IPU_LOG("Ipu read32: IPU_BP=0x%08X\n", *(u32*)&g_BP); +#endif + return ipuRegs->ipubp; + } + + return *(u32*)(((u8*)ipuRegs)+(mem&0xff)); // ipu repeats every 0x100 +} + +int ipuConstRead32(u32 x86reg, u32 mem) +{ + int workingreg, tempreg, tempreg2; + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + +// if( !(x86reg&(MEM_XMMTAG|MEM_MMXTAG)) ) { +// if( x86reg == EAX ) { +// tempreg = ECX; +// tempreg2 = EDX; +// } +// else if( x86reg == ECX ) { +// tempreg = EAX; +// tempreg2 = EDX; +// } +// else if( x86reg == EDX ) { +// tempreg = EAX; +// tempreg2 = ECX; +// } +// +// workingreg = x86reg; +// } +// else { + workingreg = EAX; + tempreg = ECX; + tempreg2 = EDX; +// } + + switch (mem){ + + case 0x10002010: // IPU_CTRL + + MOV32MtoR(workingreg, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(workingreg, ~0x3fff); + MOV32MtoR(tempreg, (u32)&g_nIPU0Data); + MOV8MtoR(workingreg, (u32)&g_BP.IFC); + + CMP32ItoR(tempreg, 8); + j8Ptr[5] = JLE8(0); + MOV32ItoR(tempreg, 8); + x86SetJ8( j8Ptr[5] ); + SHL32ItoR(tempreg, 4); + + OR8MtoR(EAX+4, (u32)&coded_block_pattern); // or ah, mem + OR8RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ctrl._u32, workingreg); +#endif + // NOTE: not updating ipuRegs->ctrl +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + return 1; + + case 0x10002020: // IPU_BP + + assert( (u32)&g_BP.FP + 1 == (u32)&g_BP.bufferhasnew ); + + MOVZX32M8toR(workingreg, (u32)&g_BP.BP); + MOVZX32M8toR(tempreg, (u32)&g_BP.FP); + AND8ItoR(workingreg, 0x7f); + ADD8MtoR(tempreg, (u32)&g_BP.bufferhasnew); + MOV8MtoR(workingreg+4, (u32)&g_BP.IFC); + + SHL32ItoR(tempreg, 16); + OR32RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ipubp, workingreg); +#endif + // NOTE: not updating ipuRegs->ipubp +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + + return 1; + + default: + // ipu repeats every 0x100 + _eeReadConstMem32(x86reg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + return 0; + } + + return 0; +} + +u64 ipuRead64(u32 mem) +{ + IPUProcessInterrupt(); + +#ifdef PCSX2_DEVBUILD + if( mem == 0x10002010 ) { + SysPrintf("reading 64bit IPU ctrl\n"); + } + if( mem == 0x10002020 ) { + SysPrintf("reading 64bit IPU top\n"); + } +#endif + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + //if(!ipuRegs->cmd.BUSY){ + if( ipuRegs->cmd.DATA&0xffffff ) { + IPU_LOG("Ipu read64: IPU_CMD=BUSY=%x, DATA=%08X\n", ipuRegs->cmd.BUSY?1:0,ipuRegs->cmd.DATA); + } +#endif + //return *(u64*)&ipuRegs->cmd; + break; + + case 0x10002030: // IPU_TOP +#ifdef IPU_LOG + IPU_LOG("Ipu read64: IPU_TOP=%x, bp = %d\n",ipuRegs->top,g_BP.BP); +#endif + //return *(u64*)&ipuRegs->top; + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu read64: Unknown=%x\n", mem); +#endif + break; + + } + return *(u64*)(((u8*)ipuRegs)+(mem&0xff)); +} + +void ipuConstRead64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)(((u8*)ipuRegs)+(mem&0xff))); + else { + MOVQMtoR(mmreg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + SetMMXstate(); + } +} + +void ipuSoftReset() +{ + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + fifo_wclear(); + coded_block_pattern = 0; + + ipuRegs->ctrl._u32 = 0; + g_BP.BP = 0; + g_BP.IFC = 0; + g_BP.FP = 0; + g_BP.bufferhasnew = 0; + ipuRegs->top = 0; + g_nCmdIndex = 0; + ipuCurCmd = 0xffffffff; + g_nCmdPos[0] = 0; g_nCmdPos[1] = 0; +} + +void ipuWrite32(u32 mem,u32 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE(value); + break; + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl._u32 = (value&0x47f30000)|(ipuRegs->ctrl._u32&0x8000ffff); + if (ipuRegs->ctrl.RST & 0x1) { // RESET + ipuSoftReset(); + } + +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CTRL=0x%08X\n",value); +#endif + + break; + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write32: Unknown=%x\n", mem); +#endif + *(u32*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuConstWrite32(u32 mem, int mmreg) +{ + iFlushCall(0); + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) PUSH32R(mmreg); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: // IPU_CMD + if( (mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + case 0x10002010: // IPU_CTRL + if( mmreg & MEM_EECONSTTAG ) { + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x47f30000; + + if( c & 0x40000000 ) { + CALLFunc((u32)ipuSoftReset); + } + else { + AND32ItoM((u32)&ipuRegs->ctrl._u32, 0x8000ffff); + OR32ItoM((u32)&ipuRegs->ctrl._u32, c); + } + } + else { + if( mmreg & MEM_XMMTAG ) SSE2_MOVD_XMM_to_R(EAX, mmreg&0xf); + else if( mmreg & MEM_MMXTAG ) MOVD32MMXtoR(EAX, mmreg&0xf); + else POP32R(EAX); + + MOV32MtoR(ECX, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(EAX, 0x47f30000); + AND32ItoR(ECX, 0x8000ffff); + OR32RtoR(EAX, ECX); + MOV32RtoM((u32)&ipuRegs->ctrl._u32, EAX); + + TEST32ItoR(EAX, 0x40000000); + j8Ptr[5] = JZ8(0); + + // reset + CALLFunc((u32)ipuSoftReset); + + x86SetJ8( j8Ptr[5] ); + } + + break; + default: + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) POP32R(mmreg); + _eeWriteConstMem32((u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +void ipuWrite64(u32 mem, u64 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE((u32)value); + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: Unknown=%x\n", mem); +#endif + *(u64*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuConstWrite64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: + _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem64( (u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +/////////////////////////////////////////// +// IPU Commands (exec on worker thread only) + +static void ipuBCLR(u32 val) { + fifo_wclear(); + g_BP.BP = val & 0x7F; + g_BP.FP = 0; + g_BP.IFC = 0; +#ifdef IPU_LOG + IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X\n", g_BP.BP); +#endif +} + +static BOOL ipuIDEC(u32 val) +{ + tIPU_CMD_IDEC idec={0, 0, 0, 0, 0, 0, 0, 0, 0}; + + *(u32*)&idec=val; +#ifdef IPU_LOG + IPU_LOG("IPU IDEC command.\n"); + if (idec.FB){ IPU_LOG(" Skip %d bits.",idec.FB);} + IPU_LOG(" Quantizer step code=0x%X.",idec.QSC); + if (idec.DTD==0){ IPU_LOG(" Does not decode DT."); + }else{ IPU_LOG(" Decodes DT.");} + if (idec.SGN==0){ IPU_LOG(" No bias."); + }else{ IPU_LOG(" Bias=128.");} + if (idec.DTE==1){ IPU_LOG(" Dither Enabled.");} + if (idec.OFM==0){ IPU_LOG(" Output format is RGB32."); + }else{ IPU_LOG(" Output format is RGB16.");} + IPU_LOG("\n"); +#endif + g_BP.BP+= idec.FB;//skip FB bits + //from IPU_CTRL + ipuRegs->ctrl.PCT = I_TYPE; //Intra DECoding;) + g_decoder.coding_type =ipuRegs->ctrl.PCT; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from IDEC value + g_decoder.quantizer_scale =idec.QSC; + g_decoder.frame_pred_frame_dct=!idec.DTD; + g_decoder.sgn =idec.SGN; + g_decoder.dte =idec.DTE; + g_decoder.ofm =idec.OFM; + //other stuff + g_decoder.dcr =1;//resets DC prediction value + + s_routine = co_create(mpeg2sliceIDEC, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + co_call(s_routine); + return s_RoutineDone; +} + +static BOOL ipuBDEC(u32 val) +{ + tIPU_CMD_BDEC bdec={0, 0, 0, 0, 0, 0, 0, 0}; + *(u32*)&bdec=val; + +#ifdef IPU_LOG + IPU_LOG("IPU BDEC(macroblock decode) command.\n"); + if (bdec.FB){ IPU_LOG(" Skip 0x%X bits.", bdec.FB);} + if (bdec.MBI){ IPU_LOG(" Intra MB.");} + else{ IPU_LOG(" Non-intra MB.");} + if (bdec.DCR){ IPU_LOG(" Resets DC prediction value.");} + else{ IPU_LOG(" Doesn't reset DC prediction value.");} + if (bdec.DT){ IPU_LOG(" Use field DCT.");} + else{ IPU_LOG(" Use frame DCT.");} + IPU_LOG(" Quantiser step=0x%X\n",bdec.QSC); +#endif + g_BP.BP+= bdec.FB;//skip FB bits + g_decoder.coding_type = I_TYPE; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from BDEC value + /* JayteeMaster: the quantizer (linear/non linear) depends on the q_scale_type */ + g_decoder.quantizer_scale =g_decoder.q_scale_type?non_linear_quantizer_scale [bdec.QSC]:bdec.QSC<<1; + g_decoder.macroblock_modes =bdec.DT ? DCT_TYPE_INTERLACED : 0; + g_decoder.dcr =bdec.DCR; + g_decoder.macroblock_modes|=bdec.MBI ? MACROBLOCK_INTRA : MACROBLOCK_PATTERN; + + memset(&mb8, 0, sizeof(struct macroblock_8)); + memset(&mb16, 0, sizeof(struct macroblock_16)); + + s_routine = co_create(mpeg2_slice, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + co_call(s_routine); + return s_RoutineDone; +} + +static BOOL ipuVDEC(u32 val) { + + switch( g_nCmdPos[0] ) { + case 0: + ipuRegs->cmd.DATA = 0; + if( !getBits32((u8*)&g_decoder.bitstream_buf, 0) ) + return FALSE; + + g_decoder.bitstream_bits = -16; + g_decoder.bitstream_buf=BigEndian(g_decoder.bitstream_buf); + + //value = BigEndian(value); + switch((val >> 26) & 3){ + case 0://Macroblock Address Increment + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + ipuRegs->cmd.DATA = get_macroblock_address_increment(&g_decoder); + break; + case 1://Macroblock Type //known issues: no error detected + g_decoder.frame_pred_frame_dct=1;//prevent DCT_TYPE_INTERLACED + g_decoder.coding_type =ipuRegs->ctrl.PCT; + ipuRegs->cmd.DATA=get_macroblock_modes(&g_decoder); + break; + case 2://Motion Code //known issues: no error detected + ipuRegs->cmd.DATA=get_motion_delta(&g_decoder,0); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + case 3://DMVector + ipuRegs->cmd.DATA=get_dmv(&g_decoder); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + } + + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + g_BP.BP+=(g_decoder.bitstream_bits+16); + if((int)g_BP.BP < 0) { + g_BP.BP += 128; + ReorderBitstream(); + } + + ipuRegs->cmd.DATA = (ipuRegs->cmd.DATA & 0xFFFF) | ((g_decoder.bitstream_bits+16) << 16); + ipuRegs->ctrl.ECD = (ipuRegs->cmd.DATA==0); + + case 1: + if( !FillInternalBuffer(&g_BP.BP,1) ) { + g_nCmdPos[0] = 1; + return FALSE; + } + + case 2: + + if( !getBits32((u8*)&ipuRegs->top, 0) ) { + g_nCmdPos[0] = 2; + return FALSE; + } + + ipuRegs->top = BigEndian(ipuRegs->top); + +#ifdef IPU_LOG + IPU_LOG("IPU VDEC command data 0x%x(0x%x). Skip 0x%X bits/Table=%d (%s), pct %d\n", + ipuRegs->cmd.DATA,ipuRegs->cmd.DATA >> 16,val & 0x3f, (val >> 26) & 3, (val >> 26) & 1 ? + ((val >> 26) & 2 ? "DMV" : "MBT") : (((val >> 26) & 2 ? "MC" : "MBAI")),ipuRegs->ctrl.PCT); +#endif + + return TRUE; + } + + assert(0); + return FALSE; +} + +static BOOL ipuFDEC(u32 val) +{ + if( !getBits32((u8*)&ipuRegs->cmd.DATA, 0) ) + return FALSE; + + ipuRegs->cmd.DATA = BigEndian(ipuRegs->cmd.DATA); + ipuRegs->top = ipuRegs->cmd.DATA; + return TRUE; +} + +static BOOL ipuSETIQ(u32 val) +{ + int i; + + if ((val >> 27) & 1){ + g_nCmdPos[0] += getBits((u8*)niq + g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); // 8*8*8 + +#ifdef IPU_LOG + IPU_LOG("Read non-intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + niq[i*8+0], niq[i*8+1], niq[i*8+2], niq[i*8+3], + niq[i*8+4], niq[i*8+5], niq[i*8+6], niq[i*8+7]); + } +#endif + }else{ + g_nCmdPos[0] += getBits((u8*)iq+8*g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); +#ifdef IPU_LOG + IPU_LOG("Read intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + iq[i*8+0], iq[i*8+1], iq[i*8+2], iq[i*8+3], + iq[i*8+4], iq[i*8+5], iq[i*8+6], iq[i*8+7]); + } +#endif + } + + return g_nCmdPos[0] == 64; +} + +static BOOL ipuSETVQ(u32 val) +{ + g_nCmdPos[0] += getBits((u8*)vqclut+g_nCmdPos[0], 256-8*g_nCmdPos[0], 1); // 16*2*8 + + if( g_nCmdPos[0] == 32 ) { +#ifdef IPU_LOG + IPU_LOG("IPU SETVQ command.\nRead VQCLUT table from IPU FIFO.\n"); + IPU_LOG( + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n" + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n", + vqclut[0] >> 10, (vqclut[0] >> 5) & 0x1F, vqclut[0] & 0x1F, + vqclut[1] >> 10, (vqclut[1] >> 5) & 0x1F, vqclut[1] & 0x1F, + vqclut[2] >> 10, (vqclut[2] >> 5) & 0x1F, vqclut[2] & 0x1F, + vqclut[3] >> 10, (vqclut[3] >> 5) & 0x1F, vqclut[3] & 0x1F, + vqclut[4] >> 10, (vqclut[4] >> 5) & 0x1F, vqclut[4] & 0x1F, + vqclut[5] >> 10, (vqclut[5] >> 5) & 0x1F, vqclut[5] & 0x1F, + vqclut[6] >> 10, (vqclut[6] >> 5) & 0x1F, vqclut[6] & 0x1F, + vqclut[7] >> 10, (vqclut[7] >> 5) & 0x1F, vqclut[7] & 0x1F, + vqclut[8] >> 10, (vqclut[8] >> 5) & 0x1F, vqclut[8] & 0x1F, + vqclut[9] >> 10, (vqclut[9] >> 5) & 0x1F, vqclut[9] & 0x1F, + vqclut[10] >> 10, (vqclut[10] >> 5) & 0x1F, vqclut[10] & 0x1F, + vqclut[11] >> 10, (vqclut[11] >> 5) & 0x1F, vqclut[11] & 0x1F, + vqclut[12] >> 10, (vqclut[12] >> 5) & 0x1F, vqclut[12] & 0x1F, + vqclut[13] >> 10, (vqclut[13] >> 5) & 0x1F, vqclut[13] & 0x1F, + vqclut[14] >> 10, (vqclut[14] >> 5) & 0x1F, vqclut[14] & 0x1F, + vqclut[15] >> 10, (vqclut[15] >> 5) & 0x1F, vqclut[15] & 0x1F); +#endif + } + + return g_nCmdPos[0] == 32; +} + +// IPU Transfers are split into 8Qwords so we need to send ALL the data +static BOOL ipuCSC(u32 val) +{ + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + *(u32*)&csc=val; + +#ifdef IPU_LOG + IPU_LOG("IPU CSC(Colorspace conversion from YCbCr) command (%d).\n",csc.MBC); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is RGB32. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } +#endif + //SysPrintf("CSC\n"); + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 3072/8 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 3072-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 3072/8 ) + return FALSE; + + ipu_csc(&mb8, &rgb32, 0); + if (csc.OFM){ + ipu_dither(&mb8, &rgb16, csc.DTE); + } + } + + if (csc.OFM){ + g_nCmdPos[1] += IPU0dma(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 32 ) + return FALSE; + } + else { + g_nCmdPos[1] += IPU0dma(((u32*)&rgb32)+4*g_nCmdPos[1], 64-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 64 ) + return FALSE; + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +// Todo - Need to add the same stop and start code as CSC +static BOOL ipuPACK(u32 val) { + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + + *(u32*)&csc=val; +#ifdef IPU_LOG + IPU_LOG("IPU PACK (Colorspace conversion from RGB32) command.\n"); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is INDX4. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } + IPU_LOG("Number of macroblocks to be converted: %d\n", csc.MBC); +#endif + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 512 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 64 ) + return FALSE; + + ipu_dither(&mb8, &rgb16, csc.DTE); + if (csc.OFM){ + ipu_vq(&rgb16, indx4); + } + } + + if (csc.OFM) { + g_nCmdPos[1] += IPU0dma(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 32 ) + return FALSE; + } + else { + g_nCmdPos[1] += IPU0dma(((u32*)indx4)+4*g_nCmdPos[1], 8-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 8 ) + return FALSE; + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +static void ipuSETTH(u32 val) { + s_thresh[0] = (val & 0xff); + s_thresh[1] = ((val>>16) & 0xff); +#ifdef IPU_LOG + IPU_LOG("IPU SETTH (Set threshold value)command %x.\n", val&0xff00ff); +#endif +} + +/////////////////////// +// IPU Worker Thread // +/////////////////////// +#define IPU_INTERRUPT(dma) { \ + if( (cpuRegs.interrupt & (1<ctrl.BUSY ) { + // wait for thread + SysPrintf("IPU BUSY!\n"); + } + + ipuRegs->ctrl.ECD = 0; + ipuRegs->ctrl.SCD = 0; //clear ECD/SCD + ipuRegs->cmd.DATA = val; + g_nCmdPos[0] = 0; + + switch (ipuRegs->cmd.CMD) { + case SCE_IPU_BCLR: + ipuBCLR(val); + IPU_INTERRUPT(DMAC_TO_IPU); + return; + + case SCE_IPU_VDEC: + + g_BP.BP+= val & 0x3F; + + // check if enough data in queue + if( ipuVDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_FDEC: + +#ifdef IPU_LOG + IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X bytes, BP 0x%X, FP %d, CHCR 0x%x\n", + val & 0x3f,g_BP.IFC,(int)g_BP.BP,g_BP.FP,((DMACh*)&PS2MEM_HW[0xb400])->chcr); +#endif + + g_BP.BP+= val & 0x3F; + + if( ipuFDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_SETTH: + ipuSETTH(val); + hwIntcIrq(INTC_IPU); + return; + + case SCE_IPU_SETIQ: +#ifdef IPU_LOG + IPU_LOG("IPU SETIQ command.\n"); +#endif +#ifdef IPU_LOG + if (val & 0x3f){ + IPU_LOG("Skip %d bits.\n", val & 0x3f); + } +#endif + g_BP.BP+= val & 0x3F; + + if( ipuSETIQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_SETVQ: + if( ipuSETVQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_CSC: + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuCSC(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + case SCE_IPU_PACK: + + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuPACK(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + + case SCE_IPU_IDEC: + FreezeMMXRegs(1); + if( ipuIDEC(val) ) { + // idec done, ipu0 done too + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + FreezeMMXRegs(0); + + break; + + case SCE_IPU_BDEC: + FreezeMMXRegs(1); + if( ipuBDEC(val) ) { + // bdec done, wait for ipu0 + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + FreezeMMXRegs(0); + + break; + } + + // have to resort to the thread + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; +} + +void IPUWorker() +{ + assert( ipuRegs->ctrl.BUSY ); + + switch (ipuCurCmd) { + case SCE_IPU_VDEC: + if( !ipuVDEC(ipuRegs->cmd.DATA) ) + return; + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_FDEC: + if( !ipuFDEC(ipuRegs->cmd.DATA) ) + return; + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_SETIQ: + if( !ipuSETIQ(ipuRegs->cmd.DATA) ) + return; + + break; + case SCE_IPU_SETVQ: + if( !ipuSETVQ(ipuRegs->cmd.DATA) ) + return; + + break; + case SCE_IPU_CSC: + if( !ipuCSC(ipuRegs->cmd.DATA) ) + return; + + break; + case SCE_IPU_PACK: + if( !ipuPACK(ipuRegs->cmd.DATA) ) + return; + + break; + + case SCE_IPU_BDEC: + case SCE_IPU_IDEC: + + FreezeMMXRegs(1); + co_call(s_routine); + if( !s_RoutineDone ) { + FreezeMMXRegs(0); + return; + } + + ipuRegs->ctrl.BUSY = 0; + ipuRegs->topbusy = 0; + ipuRegs->cmd.BUSY = 0; + ipuCurCmd = 0xffffffff; + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + + default: + SysPrintf("Unknown IPU command: %x\n", ipuRegs->cmd.CMD); + break; + } + + // success + ipuRegs->ctrl.BUSY = 0; + ipuCurCmd = 0xffffffff; + IPU_INTERRUPT(DMAC_TO_IPU); +} + +///////////////// +// Buffer reader + +// move the readbits queue +__forceinline void inc_readbits() +{ + readbits += 16; + if( readbits >= _readbits+64 ) { + + // move back + *(u64*)(_readbits) = *(u64*)(_readbits+64); + *(u64*)(_readbits+8) = *(u64*)(_readbits+72); + readbits = _readbits; + } +} + +// returns the pointer of readbits moved by 1 qword +__forceinline u8* next_readbits() +{ + return readbits + 16; +} + +// returns the pointer of readbits moved by 1 qword +u8* prev_readbits() +{ + if( readbits < _readbits+16 ) { + return _readbits+48-(readbits-_readbits); + } + + return readbits-16; +} + +void ReorderBitstream() +{ + readbits = prev_readbits(); + g_BP.bufferhasnew = 1; + //g_BP.FP++; +} + +// IPU has a 2qword internal buffer whose status is pointed by FP. +// If FP is 1, there's 1 qword in buffer. Second qword is only loaded +// incase there are less than 32bits available in the first qword. +// \return Number of bits available (clamps at 16 bits) +u8 FillInternalBuffer(u32 * pointer, u32 advance) +{ + if(g_BP.FP == 0) + { + if( fifo_wread1(next_readbits()) == 0 ) + return 0; + + g_BP.bufferhasnew = 0; + inc_readbits(); + g_BP.FP = 1; + } + else if(g_BP.FP < 2 && g_BP.bufferhasnew == 0 ) + { + // in reality, need only > 96, but IPU reads ahead + if( *(int*)pointer > 96) { + if( !fifo_wread1(next_readbits()) ) + return 0; + g_BP.FP += 1; + } + } + + if(*(int*)pointer >= 128) + { + assert( g_BP.FP >= 1 || g_BP.bufferhasnew); + inc_readbits(); + + if(advance) + { + // Incase BDEC reorders bits, we need to make sure we have the old + // data backed up. So we store the last read qword into the 2nd slot + // of the internal buffer. After that we copy the new qword read in + // the 2nd slot to the 1st slot to be read. + if( !g_BP.bufferhasnew ) + g_BP.FP--; + g_BP.bufferhasnew = 0; + } + + *pointer &= 127; + } + + return (g_BP.FP+g_BP.bufferhasnew) == 1 ? g_BP.FP*128-pointer[0] : 128; +} + +// whenever reading fractions of bytes. The low bits always come from the next byte +// while the high bits come from the current byte +u8 getBits32(u8 *address, u32 advance) +{ + register u32 mask, shift=0; + u8* readpos; + + // Check if the current BP has exceeded or reached the limit of 128 + if( FillInternalBuffer(&g_BP.BP,1) < 32 ) + return 0; + + readpos = readbits+(int)g_BP.BP/8; + + if (g_BP.BP & 7) { + + shift = g_BP.BP&7; + mask = (0xff>>shift); + mask = mask|(mask<<8)|(mask<<16)|(mask<<24); + + *(u32*)address = ((~mask&*(u32*)(readpos+1))>>(8-shift)) | (((mask)&*(u32*)readpos)<>shift); + mask = mask|(mask<<8); + + *(u16*)address = ((~mask&*(u16*)(readpos+1))>>(8-shift)) | (((mask)&*(u16*)readpos)<>shift); + + *(u8*)address = (((~mask)&readpos[1])>>(8-shift)) | (((mask)&*readpos)<> (pointer&7)) << + (8-howmuch-(pointer&7))) & 0xFF; + mask &= readbits[((pointer)>>3)]; + mask >>= 8-howmuch-(pointer&7); + pointer += howmuch; + size -= howmuch; + shift -= howmuch; + *address |= mask << shift; + } + + ++address; + } + else + { + u8* readmem; + while (size) + { + if( FillInternalBuffer(&pointer,advance) < 8 ) + return address-oldaddr; + + howmuch = min(128-pointer, size); + size -= howmuch; + + readmem = readbits + (pointer>>3); + pointer += howmuch; + howmuch >>= 3; + + while(howmuch >= 4) { + *(u32*)address = *(u32*)readmem; + howmuch -= 4; + address += 4; + readmem += 4; + } + + switch(howmuch) { + case 3: address[2] = readmem[2]; + case 2: address[1] = readmem[1]; + case 1: address[0] = readmem[0]; + case 0: + break; + default: __assume(0); + } + + address += howmuch; + } + } + + // If not advance then reset the Reading buffer value + if(advance) g_BP.BP = pointer; + else readbits = oldbits; // restore the last pointer + + return address-oldaddr; +} + +///////////////////// CORE FUNCTIONS ///////////////// +void Skl_YUV_To_RGB32_MMX(u8 *RGB, const int Dst_BpS, const u8 *Y, const u8 *U, const u8 *V, + const int Src_BpS, const int Width, const int Height); + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn){ + int i; + u8* p = (u8*)rgb32; + + convert_init.start(convert_init.id, (u8*)rgb32, CONVERT_FRAME); + convert_init.copy(convert_init.id, (u8*)mb8->Y, (u8*)mb8->Cr, (u8*)mb8->Cb, 0); + + // do alpha processing +// if( cpucaps.hasStreamingSIMD2Extensions ) { +// int i; +// u8* p = (u8*)rgb32; +// +// __asm { +// movaps xmm6, s_thresh +// pshufd xmm7, xmm6, 0xee +// pshufd xmm6, xmm6, 0x44 +// pxor xmm5, xmm5 +// } +// +// for(i = 0; i < 64; i += 4, p += 64) { +// // process 2 qws at a time +// __asm { +// // extract 8 dwords +// mov edi, p +// movaps xmm0, qword ptr [edi] +// movaps xmm1, qword ptr [edi+16] +// movaps xmm2, qword ptr [edi+32] +// movaps xmm3, qword ptr [edi+48] +// +// +// } + // fixes suikoden5 + if( s_thresh[0] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + if( p[0] < s_thresh[0] && p[1] < s_thresh[0] && p[2] < s_thresh[0] ) + *(u32*)p = 0; + else + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else if( s_thresh[1] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else { + for(i = 0; i < 64; i++, p += 16) { + p[3] = p[7] = p[11] = p[15] = 0x80; + } + } +} + +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte){ + SysPrintf("IPU: Dither not implemented"); +} + +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4){ + SysPrintf("IPU: VQ not implemented"); +} + +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16){ + unsigned char *s=(unsigned char*)mb8; + signed short *d=(signed short*)mb16; + int i; + for (i=0; i< 256; i++) *d++ = *s++; //Y bias - 16 + for (i=0; i< 64; i++) *d++ = *s++; //Cr bias - 128 + for (i=0; i< 64; i++) *d++ = *s++; //Cb bias - 128 + /*for(i = 0; i < 384/(16*6); ++i, s += 16*4, d += 16*4) { + __m128i r0, r1, r2, r3, r4, r5, r6, r7; + + r0 = _mm_load_si128((__m128i*)s); + r2 = _mm_load_si128((__m128i*)s+1); + r4 = _mm_load_si128((__m128i*)s+2); + r6 = _mm_load_si128((__m128i*)s+3); + + // signed shift + r1 = _mm_srai_epi16(_mm_unpackhi_epi8(r0, r0), 8); + r0 = _mm_srai_epi16(_mm_unpacklo_epi8(r0, r0), 8); + r3 = _mm_srai_epi16(_mm_unpackhi_epi8(r2, r2), 8); + r2 = _mm_srai_epi16(_mm_unpacklo_epi8(r2, r2), 8); + r5 = _mm_srai_epi16(_mm_unpackhi_epi8(r4, r4), 8); + r4 = _mm_srai_epi16(_mm_unpacklo_epi8(r4, r4), 8); + r7 = _mm_srai_epi16(_mm_unpackhi_epi8(r6, r6), 8); + r6 = _mm_srai_epi16(_mm_unpacklo_epi8(r6, r6), 8); + + _mm_store_si128((__m128i*)d, r0); + _mm_store_si128((__m128i*)d+1, r1); + _mm_store_si128((__m128i*)d+2, r2); + _mm_store_si128((__m128i*)d+3, r3); + _mm_store_si128((__m128i*)d+4, r4); + _mm_store_si128((__m128i*)d+5, r5); + _mm_store_si128((__m128i*)d+6, r6); + _mm_store_si128((__m128i*)d+7, r7); + }*/ +} + +///////////////////// IPU DMA //////////////////////// +void fifo_wclear() +{ + //assert( g_BP.IFC == 0 ); + //memset(fifo_input,0,sizeof(fifo_input)); + g_BP.IFC = 0; + readwpos = 0; + writewpos = 0; +} + +int fifo_wread(void *value, int size) +{ + int transsize, firstsize; + + transsize = size; + + // transfer what is left in fifo + firstsize = min((int)g_BP.IFC, size); + g_BP.IFC -= firstsize; + size -= firstsize; + + while( firstsize-- > 0) { + + // transfer firstsize qwords, split into two transfers + ((u32*)value)[0] = fifo_input[readwpos]; + ((u32*)value)[1] = fifo_input[readwpos+1]; + ((u32*)value)[2] = fifo_input[readwpos+2]; + ((u32*)value)[3] = fifo_input[readwpos+3]; + readwpos = (readwpos + 4) & 31; + value = (u32*)value + 4; + } + + if(size > 0) { + + // fifo is too small, so have to get from DMA + while( IPU1dma() > 0 ) { + + firstsize = min(size, (int)g_BP.IFC); + size -= firstsize; + g_BP.IFC -= firstsize; + + while( firstsize-- > 0) { + + // transfer firstsize qwords, split into two transfers + ((u32*)value)[0] = fifo_input[readwpos]; + ((u32*)value)[1] = fifo_input[readwpos+1]; + ((u32*)value)[2] = fifo_input[readwpos+2]; + ((u32*)value)[3] = fifo_input[readwpos+3]; + readwpos = (readwpos + 4) & 31; + value = (u32*)value + 4; + } + + if( size == 0 ) + return transsize; + } + } + + return transsize-size; +} + +int fifo_wread1(void *value) +{ + // wait until enough data + if( g_BP.IFC == 0 ) { + if( IPU1dma() == 0 ) + return 0; + + assert( g_BP.IFC > 0 ); + } + + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_input[readwpos]; + ((u32*)value)[1] = fifo_input[readwpos+1]; + ((u32*)value)[2] = fifo_input[readwpos+2]; + ((u32*)value)[3] = fifo_input[readwpos+3]; + readwpos = (readwpos + 4) & 31; + g_BP.IFC--; + return 1; +} + +int fifo_wwrite(u32* pMem, int size) +{ + int transsize; + int firsttrans = min(size, 8-(int)g_BP.IFC); + + g_BP.IFC+=firsttrans; + transsize = firsttrans; + + while(transsize-- > 0) { + fifo_input[writewpos] = pMem[0]; + fifo_input[writewpos+1] = pMem[1]; + fifo_input[writewpos+2] = pMem[2]; + fifo_input[writewpos+3] = pMem[3]; + writewpos = (writewpos+4)&31; + pMem +=4; + } + + return firsttrans; +} + +#define IPU1chain() { \ + int qwc = ipu1dma->qwc; \ + pMem = (u32*)dmaGetAddr(ipu1dma->madr); \ + if (pMem == NULL) { SysPrintf("ipu1dma NULL!\n"); return totalqwc; } \ + qwc = fifo_wwrite(pMem, qwc); \ + ipu1dma->madr += qwc<< 4; \ + ipu1dma->qwc -= qwc; \ + totalqwc += qwc; \ + if( ipu1dma->qwc > 0 ) { \ + g_nDMATransfer |= IPU_DMA_ACTV1; \ + return totalqwc; \ + } \ +} + +int IPU1dma() +{ + u32 *ptag, *pMem; + int done=0; + int ipu1cycles = 0; + int totalqwc = 0; + + assert( !(ipu1dma->chcr&0x40) ); + + if( !(ipu1dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc > 0 ) { + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer&IPU_DMA_DOTIE1)) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + + if( (ipu1dma->chcr&0xc) == 0 ) { + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + else { + u32 tag = ipu1dma->chcr; // upper bits describe current tag + + if ((ipu1dma->chcr & 0x80) && (tag&0x80000000)) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(tag&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); +#ifdef IPU_LOG + IPU_LOG("dmaIrq Set\n"); +#endif + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + switch( tag&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + } + } + + if ((ipu1dma->chcr & 0xc) == 0 && ipu1dma->qwc == 0) { // Normal Mode + //SysPrintf("ipu1 normal empty qwc?\n"); + return totalqwc; + } + + // Transfer Dn_QWC from Dn_MADR to GIF + if( ipu1dma->qwc > 0 ) { + IPU1chain(); + } + if ((ipu1dma->chcr & 0xc) == 0 ) { // Normal Mode + } + else { + // Chain Mode + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + ipu1cycles+=1; // Add 1 cycles from the QW read for the tag + + ipu1dma->chcr = ( ipu1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + ipu1dma->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + //ipu1dma->madr = ptag[1]; //MADR = ADDR field + +#ifdef IPU_LOG + IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x\n", + ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); +#endif + + //done = hwDmacSrcChainWithStack(ipu1dma, id); + switch(ptag[0] & 0x70000000) { + case 0x00000000: // refe + // do not change tadr + ipu1dma->madr = ptag[1]; + done = 1; + break; + + case 0x10000000: // cnt + ipu1dma->madr = ipu1dma->tadr + 16; + // Set the taddr to the next tag + ipu1dma->tadr += 16 + (ipu1dma->qwc << 4); + break; + + case 0x20000000: // next + ipu1dma->madr = ipu1dma->tadr + 16; + ipu1dma->tadr = ptag[1]; + break; + + case 0x30000000: // ref + ipu1dma->madr = ptag[1]; + ipu1dma->tadr += 16; + break; + + case 0x70000000: // end + // do not change tadr + ipu1dma->madr = ipu1dma->tadr + 16; + done = 1; + break; + + default: + #ifdef IPU_LOG + IPU_LOG("ERROR: different transfer mode!, Please report to PCSX2 Team\n"); + #endif + break; + } + + if( ptag[0] & 0x80000000 ) + g_nDMATransfer |= IPU_DMA_DOTIE1; + else + g_nDMATransfer &= ~IPU_DMA_DOTIE1; + + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (ptag[0]&0x80000000) ) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + if( done ) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(ptag[0]&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); + } + + INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + } + + switch( ptag[0]&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + } + + INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS); + return totalqwc; +} + +int IPU0dma(const void* ptr, int size) +{ + int readsize; + void* pMem; + + if( !(ipu0dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc == 0) + return 0; + + assert( !(ipu0dma->chcr&0x40) ); + +#ifdef IPU_LOG + IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx, ipuout_fifo.count=%x\n", + ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc, size); +#endif + + assert((ipu0dma->chcr & 0xC) == 0 ); + pMem = (u32*)dmaGetAddr(ipu0dma->madr); + + readsize = min(ipu0dma->qwc, size); + + memcpy_amd(pMem, ptr, readsize<<4); + ipu0dma->madr += readsize<< 4; + ipu0dma->qwc -= readsize; // note: qwc is u16 + + if(ipu0dma->qwc == 0) { + if ((psHu32(DMAC_CTRL) & 0x30) == 0x30) { // STS == fromIPU + psHu32(DMAC_STADR) = ipu0dma->madr; + switch (psHu32(DMAC_CTRL) & 0xC0) { + case 0x80: // GIF + g_nDMATransfer |= IPU_DMA_GIFSTALL; + break; + } + } + + INT(DMAC_FROM_IPU, (readsize*BIAS)); + } + + return readsize; +} + +void dmaIPU0() // fromIPU +{ + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +void dmaIPU1() // toIPU +{ + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +int ipu0Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu0Interrupt:\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT0 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT0; + } + + if( g_nDMATransfer & IPU_DMA_GIFSTALL ) { + // gif + g_nDMATransfer &= ~IPU_DMA_GIFSTALL; + dmaGIF(); + } + + if( g_nDMATransfer & IPU_DMA_TIE0 ) { + g_nDMATransfer &= ~IPU_DMA_TIE0; + hwDmacIrq(DMAC_FROM_IPU); + } + else { + ipu0dma->chcr &= ~0x100; + hwDmacIrq(DMAC_FROM_IPU); + } + + return 1; +} + +int ipu1Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu1Interrupt:\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT1 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT1; + } + + if( g_nDMATransfer & IPU_DMA_TIE1 ) { + g_nDMATransfer &= ~IPU_DMA_TIE1; + hwDmacIrq(DMAC_TO_IPU); + } + else { + ipu1dma->chcr &= ~0x100; + hwDmacIrq(DMAC_TO_IPU); + } + + return 1; +} diff --git a/IPU/IPU.h b/IPU/IPU.h new file mode 100644 index 0000000000..2f05c5f750 --- /dev/null +++ b/IPU/IPU.h @@ -0,0 +1,209 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IPU_H__ +#define __IPU_H__ + +#include "Common.h" + +#ifdef __WIN32__ +#pragma pack(1) +#endif + +// +// Bitfield Structure +// +typedef union { + struct { + u32 OPTION : 28; // VDEC decoded value + u32 CMD : 4; // last command + u32 _BUSY; + }; + struct { + u32 DATA; + u32 BUSY; + }; +} tIPU_CMD; + +#define IPU_CTRL_IFC_M (0x0f<< 0) +#define IPU_CTRL_OFC_M (0x0f<< 4) +#define IPU_CTRL_CBP_M (0x3f<< 8) +#define IPU_CTRL_ECD_M (0x01<<14) +#define IPU_CTRL_SCD_M (0x01<<15) +#define IPU_CTRL_IDP_M (0x03<<16) +#define IPU_CTRL_AS_M (0x01<<20) +#define IPU_CTRL_IVF_M (0x01<<21) +#define IPU_CTRL_QST_M (0x01<<22) +#define IPU_CTRL_MP1_M (0x01<<23) +#define IPU_CTRL_PCT_M (0x07<<24) +#define IPU_CTRL_RST_M (0x01<<30) +#define IPU_CTRL_BUSY_M (0x01<<31) + +#define IPU_CTRL_IFC_O ( 0) +#define IPU_CTRL_OFC_O ( 4) +#define IPU_CTRL_CBP_O ( 8) +#define IPU_CTRL_ECD_O (14) +#define IPU_CTRL_SCD_O (15) +#define IPU_CTRL_IDP_O (16) +#define IPU_CTRL_AS_O (20) +#define IPU_CTRL_IVF_O (21) +#define IPU_CTRL_QST_O (22) +#define IPU_CTRL_MP1_O (23) +#define IPU_CTRL_PCT_O (24) +#define IPU_CTRL_RST_O (30) +#define IPU_CTRL_BUSY_O (31) + + +// +// Bitfield Structure +// +typedef union { + struct { + u32 IFC : 4; // Input FIFO counter + u32 OFC : 4; // Output FIFO counter + u32 CBP : 6; // Coded block pattern + u32 ECD : 1; // Error code pattern + u32 SCD : 1; // Start code detected + u32 IDP : 2; // Intra DC precision + u32 resv0 : 2; + u32 AS : 1; // Alternate scan + u32 IVF : 1; // Intra VLC format + u32 QST : 1; // Q scale step + u32 MP1 : 1; // MPEG1 bit strea + u32 PCT : 3; // Picture Type + u32 resv1 : 3; + u32 RST : 1; // Reset + u32 BUSY : 1; // Busy + }; + u32 _u32; +} tIPU_CTRL; + +#define IPU_BP_BP_M (0x7f<< 0) +#define IPU_BP_IFC_M (0x0f<< 8) +#define IPU_BP_FP_M (0x03<<16) + +#define IPU_BP_BP_O ( 0) +#define IPU_BP_IFC_O ( 8) +#define IPU_BP_FP_O (16) + + +// +// Bitfield Structure +// +typedef struct { + u32 BP; // Bit stream point + u16 IFC; // Input FIFO counter + u8 FP; // FIFO point + u8 bufferhasnew; +} tIPU_BP; + +#ifdef __WIN32__ +#pragma pack() +#endif + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 3; + u32 DTD : 1; + u32 SGN : 1; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_IDEC; + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 4; + u32 DT : 1; + u32 DCR : 1; + u32 MBI : 1; + u32 cmd : 4; +} tIPU_CMD_BDEC; + +typedef struct { + u32 MBC :11; + u32 UN2 :15; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_CSC; + +#define SCE_IPU_BCLR 0x0 +#define SCE_IPU_IDEC 0x1 +#define SCE_IPU_BDEC 0x2 +#define SCE_IPU_VDEC 0x3 +#define SCE_IPU_FDEC 0x4 +#define SCE_IPU_SETIQ 0x5 +#define SCE_IPU_SETVQ 0x6 +#define SCE_IPU_CSC 0x7 +#define SCE_IPU_PACK 0x8 +#define SCE_IPU_SETTH 0x9 + +typedef struct _IPUregisters { + tIPU_CMD cmd; + u32 dummy0[2]; + tIPU_CTRL ctrl; + u32 dummy1[3]; + u32 ipubp; + u32 dummy2[3]; + u32 top; + u32 topbusy; + u32 dummy3[2]; +} IPUregisters; + +#ifdef WIN32_VIRTUAL_MEM +#define ipuRegs ((IPUregisters*)(PS2MEM_HW+0x2000)) +#else +extern IPUregisters g_ipuRegsReal; +#define ipuRegs (&g_ipuRegsReal) +#endif + +void dmaIPU0(); +void dmaIPU1(); + +int ipuInit(); +void ipuReset(); +void ipuShutdown(); +int ipuFreeze(gzFile f, int Mode); +BOOL ipuCanFreeze(); + +u32 ipuRead32(u32 mem); +int ipuConstRead32(u32 x86reg, u32 mem); + +u64 ipuRead64(u32 mem); +void ipuConstRead64(u32 mem, int mmreg); + +void ipuWrite32(u32 mem,u32 value); +void ipuConstWrite32(u32 mem, int mmreg); + +void ipuWrite64(u32 mem,u64 value); +void ipuConstWrite64(u32 mem, int mmreg); + +int ipu0Interrupt(); +int ipu1Interrupt(); + +u8 getBits32(u8 *address, u32 advance); +u8 getBits16(u8 *address, u32 advance); +u8 getBits8(u8 *address, u32 advance); +int getBits(u8 *address, u32 size, u32 advance); + +#endif diff --git a/IPU/idct_mmx.obj b/IPU/idct_mmx.obj new file mode 100644 index 0000000000..9f7d313608 Binary files /dev/null and b/IPU/idct_mmx.obj differ diff --git a/IPU/mpeg2lib/Idct.c b/IPU/mpeg2lib/Idct.c new file mode 100644 index 0000000000..6529956edc --- /dev/null +++ b/IPU/mpeg2lib/Idct.c @@ -0,0 +1,302 @@ +/* + * idct.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//#include +#include "Common.h" +#include "ix86/ix86.h" + +#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ +#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */ +#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */ +#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */ +#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */ +#define W7 565 /* 2048*sqrt (2)*cos (7*pi/16) */ +#define clp(val,res) res = (val < 0) ? 0 : ((val > 255) ? 255 : val); +#define clp2(val,res) res = (val < -255) ? -255 : ((val > 255) ? 255 : val); +/* idct main entry point */ +void (* mpeg2_idct_copy) (s16 * block, u8 * dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16 * dest, int stride); + +/* + * In legal streams, the IDCT output should be between -384 and +384. + * In corrupted streams, it is possible to force the IDCT output to go + * to +-3826 - this is the worst case for a column IDCT where the + * column inputs are 16-bit values. + */ +static u8 clip_lut[1024]; +#define CLIP(i) ((clip_lut+384)[(i)]) + +#if 0 +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + t0 = W0*d0 + W1*d1; \ + t1 = W0*d1 - W1*d0; \ +} while (0) +#else +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + int tmp = W0 * (d0 + d1); \ + t0 = tmp + (W1 - W0) * d1; \ + t1 = tmp - (W1 + W0) * d0; \ +} while (0) +#endif + +static void idct_row (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + /* shortcut */ + if (!(block[1] | ((s32 *)block)[1] | ((s32 *)block)[2] | + ((s32 *)block)[3])) { + u32 tmp = (u16) (block[0] << 3); + tmp |= tmp << 16; + ((s32 *)block)[0] = tmp; + ((s32 *)block)[1] = tmp; + ((s32 *)block)[2] = tmp; + ((s32 *)block)[3] = tmp; + return; + } + + d0 = (block[0] << 11) + 128; + d1 = block[1]; + d2 = block[2] << 11; + d3 = block[3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[4]; + d1 = block[5]; + d2 = block[6]; + d3 = block[7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 -= t2; + t1 -= t3; + b1 = ((t0 + t1) * 181) >> 8; + b2 = ((t0 - t1) * 181) >> 8; + + block[0] = (a0 + b0) >> 8; + block[1] = (a1 + b1) >> 8; + block[2] = (a2 + b2) >> 8; + block[3] = (a3 + b3) >> 8; + block[4] = (a3 - b3) >> 8; + block[5] = (a2 - b2) >> 8; + block[6] = (a1 - b1) >> 8; + block[7] = (a0 - b0) >> 8; +} + +static void idct_col (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + d0 = (block[8*0] << 11) + 65536; + d1 = block[8*1]; + d2 = block[8*2] << 11; + d3 = block[8*3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[8*4]; + d1 = block[8*5]; + d2 = block[8*6]; + d3 = block[8*7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 = (t0 - t2) >> 8; + t1 = (t1 - t3) >> 8; + b1 = (t0 + t1) * 181; + b2 = (t0 - t1) * 181; + + block[8*0] = (a0 + b0) >> 17; + block[8*1] = (a1 + b1) >> 17; + block[8*2] = (a2 + b2) >> 17; + block[8*3] = (a3 + b3) >> 17; + block[8*4] = (a3 - b3) >> 17; + block[8*5] = (a2 - b2) >> 17; + block[8*6] = (a1 - b1) >> 17; + block[8*7] = (a0 - b0) >> 17; +} + +static void mpeg2_idct_copy_c (s16 * block, u8 * dest, + const int stride) +{ + int i; + + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = CLIP (block[0]); + dest[1] = CLIP (block[1]); + dest[2] = CLIP (block[2]); + dest[3] = CLIP (block[3]); + dest[4] = CLIP (block[4]); + dest[5] = CLIP (block[5]); + dest[6] = CLIP (block[6]); + dest[7] = CLIP (block[7]); + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void mpeg2_idct_add_c (const int last, s16 * block, + /*u8*/s16 * dest, const int stride) +{ + int i; + + if (last != 129 || (block[0] & 7) == 4) { + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = block[0]; + dest[1] = block[1]; + dest[2] = block[2]; + dest[3] = block[3]; + dest[4] = block[4]; + dest[5] = block[5]; + dest[6] = block[6]; + dest[7] = block[7]; + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); + } else { + int DC; + + DC = (block[0] + 4) >> 3; + block[0] = block[63] = 0; + i = 8; + do { + dest[0] = DC; + dest[1] = DC; + dest[2] = DC; + dest[3] = DC; + dest[4] = DC; + dest[5] = DC; + dest[6] = DC; + dest[7] = DC; + dest += stride; + } while (--i); + } +} + +u8 mpeg2_scan_norm[64] = { + /* Zig-Zag scan pattern */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +u8 mpeg2_scan_alt[64] = { + /* Alternate scan pattern */ + 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +/* idct_mmx.c */ +void mpeg2_idct_copy_mmxext (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmxext (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_copy_mmx (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmx (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_mmx_init (void); + +void mpeg2_idct_init() +{ +#ifndef __VCNET2005__ + int i, j; + +/* if(hasMultimediaExtensions == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmx; + mpeg2_idct_add = mpeg2_idct_add_mmx; + mpeg2_idct_mmx_init (); + }else if(hasMultimediaExtensionsExt == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmxext; + mpeg2_idct_add = mpeg2_idct_add_mmxext; + mpeg2_idct_mmx_init (); + }else*/ + { + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } + } + +#else //blah vcnet2005 idiocity :D + int i,j; + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } +#endif +} diff --git a/IPU/mpeg2lib/Mpeg.c b/IPU/mpeg2lib/Mpeg.c new file mode 100644 index 0000000000..67024e7386 --- /dev/null +++ b/IPU/mpeg2lib/Mpeg.c @@ -0,0 +1,1252 @@ +/* + * Mpeg.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Mpeg.h" +#include "Vlc.h" + +#define BigEndian _byteswap_ulong + +extern void (* mpeg2_idct_copy) (s16 * block, u8* dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +extern void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16* dest, int stride); + +extern int IPU0dma(const void* pMem, int size); + +/* JayteeMaster: remove static attribute */ +/*static */int non_linear_quantizer_scale [] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 +}; + +extern tIPU_BP g_BP; + +/* Bitstream and buffer needs to be realocated inorder for sucessful + reading of the old data. Here the old data stored in the 2nd slot + of the internal buffer is copied to 1st slot, and the new data read + into 1st slot is copied to the 2nd slot. Which will later be copied + back to the 1st slot when 128bits have been read. +*/ +extern void ReorderBitstream(); + +int get_macroblock_modes (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int macroblock_modes; + const MBtab * tab; + + switch (decoder->coding_type) { + case I_TYPE: + + macroblock_modes = UBITS (bit_buf, 2); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_I + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if ((! (decoder->frame_pred_frame_dct)) && + (decoder->picture_structure == FRAME_PICTURE)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + + return macroblock_modes; + + case P_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_P + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case B_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + tab = MB_B + macroblock_modes; + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (! (macroblock_modes & MACROBLOCK_INTRA)) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_INTRA) + goto intra; + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + intra: + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case D_TYPE: + + macroblock_modes = UBITS (bit_buf, 1); + if( macroblock_modes == 0 ) + return 0; // error + DUMPBITS (bit_buf, bits, 1); + return MACROBLOCK_INTRA; + + default: + return 0; + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_quantizer_scale (decoder_t * const decoder) +{ + int quantizer_scale_code; + + quantizer_scale_code = UBITS (decoder->bitstream_buf, 5); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 5); + + if (decoder->q_scale_type) return non_linear_quantizer_scale [quantizer_scale_code]; + else return quantizer_scale_code << 1; +} + +static int get_coded_block_pattern (decoder_t * const decoder) +{ + const CBPtab * tab; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + if (decoder->bitstream_buf >= 0x20000000) { + tab = CBP_7 + (UBITS (decoder->bitstream_buf, 7) - 16); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; + } + + tab = CBP_9 + UBITS (decoder->bitstream_buf, 9); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; +} + +static int get_luma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_lum_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 3); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_chroma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_chrom_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 2); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len + 1); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#define SATURATE(val) \ +do { \ + if (((u32)(val + 2048) > 4095)) \ + val = SBITS (val, 1) ^ 2047; \ +} while (0) + +static void get_intra_block_B14 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static void get_intra_block_B15 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x04000000) { + + tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) { + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else { + /* end of block. I commented out this code because if we */ + /* dont exit here we will still exit at the later test :) */ + /* if (i >= 128) break; */ /* end of block */ + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check against buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + } else if (bit_buf >= 0x02000000) { + tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>28) != 0x6 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 4); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_non_intra_block (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + s16 * dest; + + i = -1; + mismatch = 1; + dest = decoder->DCTblock; + + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void get_mpeg1_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = 0; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_mpeg1_non_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = -1; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + val = 2 * (val + SBITS (val, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +} + +static void slice_intra_DCT (decoder_t * const decoder, const int cc, + u8 * const dest, const int stride) +{ + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + /* Get the intra DC coefficient and inverse quantize it */ + if (cc == 0) decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder); + else decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder); + decoder->DCTblock[0] = decoder->dc_dct_pred[cc] << (3 - decoder->intra_dc_precision); + + if (decoder->mpeg1) get_mpeg1_intra_block (decoder); + else if (decoder->intra_vlc_format){ + get_intra_block_B15 (decoder); + }else{ + get_intra_block_B14 (decoder); + } + + mpeg2_idct_copy (decoder->DCTblock, dest, stride); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void slice_non_intra_DCT (decoder_t * const decoder, + /*u8*/s16 * const dest, const int stride){ + int last; + memset(decoder->DCTblock,0,sizeof(decoder->DCTblock)); + if (decoder->mpeg1) last = get_mpeg1_non_intra_block (decoder); + else last = get_non_intra_block (decoder); + + mpeg2_idct_add (last, decoder->DCTblock, dest, stride); +} + +extern int coded_block_pattern; +extern u8 FillInternalBuffer(u32 * pointer, u32 advance); +extern decoder_t g_decoder; +extern int g_nIPU0Data; // or 0x80000000 whenever transferring +extern u8* g_pIPU0Pointer; + +void mpeg2sliceIDEC(void* pdone) +{ + u32 read; + decoder_t * decoder = &g_decoder; + + *(int*)pdone = 0; + bitstream_init(decoder); + + decoder->dc_dct_pred[0] = + decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + decoder->mbc=0; + + if (UBITS (decoder->bitstream_buf, 2) == 0) + { + ipuRegs->ctrl.SCD = 0; + }else{ + while (1) { + int DCT_offset, DCT_stride; + int mba_inc; + const MBAtab * mba; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + decoder->macroblock_modes = get_macroblock_modes (decoder); + + /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */ + if (decoder->macroblock_modes & MACROBLOCK_QUANT)//only IDEC + decoder->quantizer_scale = get_quantizer_scale (decoder); + + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + } + + // Send The MacroBlock via DmaIpuFrom + if (decoder->ofm==0){ + ipu_csc(decoder->mb8, decoder->rgb32, decoder->sgn); + + g_nIPU0Data = 64; + g_pIPU0Pointer = (u8*)decoder->rgb32; + while(g_nIPU0Data > 0) { + read = IPU0dma(g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ) + co_resume(); + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + else{ + ipu_dither(decoder->mb8, decoder->rgb16, decoder->dte); + + g_nIPU0Data = 32; + g_pIPU0Pointer = (u8*)decoder->rgb16; + while(g_nIPU0Data > 0) { + read = IPU0dma(g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ) + co_resume(); + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + decoder->mbc++; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + mba_inc = 0; + while (1) { + if (decoder->bitstream_buf >= 0x10000000) { + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + break; + } else if (decoder->bitstream_buf >= 0x03000000) { + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + break; + } else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + mba_inc += 33; + /* pass through */ + case 15: /* macroblock_stuffing (MPEG1 only) */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + continue; + default: /* end of slice/frame, or error? */ + { + int i; + ipuRegs->ctrl.SCD = 1; + ipuRegs->ctrl.ECD=0; + coded_block_pattern=decoder->coded_block_pattern; + + for (i=0; i<2; i++) { + u8 byte; + while(!getBits8(&byte, 0)) + co_resume(); + if (byte == 0) break; + g_BP.BP+= 8; + } + g_BP.BP-=32;//bitstream_init takes 32 bits + + while(!FillInternalBuffer(&g_BP.BP,1)) + co_resume(); + while(!getBits32((u8*)&ipuRegs->top, 0)) + co_resume(); + ipuRegs->top = BigEndian(ipuRegs->top); + *(int*)pdone = 1; + co_exit(); + } + } + } + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + mba_inc += mba->mba; + + if (mba_inc) { + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + do { + decoder->mbc++; + } while (--mba_inc); + } + } + } + + ipuRegs->ctrl.ECD=!ipuRegs->ctrl.SCD; + + coded_block_pattern=decoder->coded_block_pattern; + + g_BP.BP-=32;//bitstream_init takes 32 bits + + while(!FillInternalBuffer(&g_BP.BP,1)) + co_resume(); + while(!getBits32((u8*)&ipuRegs->top, 0)) + co_resume(); + ipuRegs->top = BigEndian(ipuRegs->top); + *(int*)pdone = 1; + co_exit(); +} + +void mpeg2_slice(void* pdone) +{ + int DCT_offset, DCT_stride; + u8 bit8=0; + u32 fp = g_BP.FP; + u32 bp; + decoder_t * decoder = &g_decoder; + u32 size = 0; + + *(int*)pdone = 0; + ipuRegs->ctrl.ECD = 0; + + bitstream_init (decoder); + + if (decoder->dcr) + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + ipu_copy(decoder->mb8,decoder->mb16); + } else { + if (decoder->macroblock_modes & MACROBLOCK_PATTERN) { + decoder->coded_block_pattern = get_coded_block_pattern (decoder); + /* JayteeMaster: changed from mb8 to mb16 and from u8 to s16 */ + if (decoder->coded_block_pattern & 0x20) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y, DCT_stride); + if (decoder->coded_block_pattern & 0x10) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x08) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset, DCT_stride); + if (decoder->coded_block_pattern & 0x04) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x2) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cb, decoder->stride>>1); + if (decoder->coded_block_pattern & 0x1) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cr, decoder->stride>>1); + + } + } + + //Send The MacroBlock via DmaIpuFrom + size = 0; // Reset + + ipuRegs->ctrl.SCD=0; + coded_block_pattern=decoder->coded_block_pattern; + + //FillInternalBuffer(&g_BP.BP, 1); + + bp = g_BP.BP; + g_BP.BP+=decoder->bitstream_bits-16; + + // BP goes from 0 to 128, so negative values mean to read old buffer + // so we minus from 128 to get the correct BP + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + g_nIPU0Data = 48; + g_pIPU0Pointer = (u8*)decoder->mb16; + while(g_nIPU0Data > 0) { + size = IPU0dma(g_pIPU0Pointer,g_nIPU0Data); + if( size == 0 ) + co_resume(); + else { + g_pIPU0Pointer += size*16; + g_nIPU0Data -= size; + } + } + + IPU_LOG("BDEC %x, %d\n",g_BP.BP,g_BP.FP); + + while( !getBits8((u8*)&bit8, 0) ) + co_resume(); + if (bit8==0) ipuRegs->ctrl.SCD = 1; + + while(!getBits32((u8*)&ipuRegs->top, 0)) + co_resume(); + ipuRegs->top = BigEndian(ipuRegs->top); + + *(int*)pdone = 1; + co_exit(); +} + +int get_motion_delta (decoder_t * const decoder, + const int f_code) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int delta; + int sign; + const MVtab * tab; + + if ( (bit_buf & 0x80000000) ) { + DUMPBITS (bit_buf, bits, 1); + return 0x00010000; + } else if ( (bit_buf & 0xf0000000) || ((bit_buf & 0xfc000000)==0x0c000000) ) { + + tab = MV_4 + UBITS (bit_buf, 4); + delta = (tab->delta << f_code) + 1; + bits += tab->len + f_code + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) + delta += UBITS (bit_buf, f_code); + bit_buf <<= f_code; + + return (delta ^ sign) - sign; + + } else { + + tab = MV_10 + UBITS (bit_buf, 10); + delta = (tab->delta << f_code) + 1; + bits += tab->len + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) { + NEEDBITS (bit_buf, bits, bit_ptr); + delta += UBITS (bit_buf, f_code); + DUMPBITS (bit_buf, bits, f_code); + } + + return (delta ^ sign) - sign; + + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_dmv (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DMVtab * tab; + + tab = DMV_2 + UBITS (bit_buf, 2); + DUMPBITS (bit_buf, bits, tab->len); + return tab->dmv; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_macroblock_address_increment(decoder_t * const decoder){ + const MBAtab *mba; + + if (decoder->bitstream_buf >= 0x10000000) + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + else if (decoder->bitstream_buf >= 0x03000000) + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x23; + case 15: /* macroblock_stuffing (MPEG1 only) */ + if (decoder->mpeg1){ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x22; + } + default: + return 0;//error + } + + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + return mba->mba + 1; +} diff --git a/IPU/mpeg2lib/Mpeg.h b/IPU/mpeg2lib/Mpeg.h new file mode 100644 index 0000000000..e866bfe722 --- /dev/null +++ b/IPU/mpeg2lib/Mpeg.h @@ -0,0 +1,185 @@ +/* + * Mpeg.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MPEG_H__ +#define __MPEG_H__ + +#include "Common.h" + +/* macroblock modes */ +#define MACROBLOCK_INTRA 1 +#define MACROBLOCK_PATTERN 2 +#define MACROBLOCK_MOTION_BACKWARD 4 +#define MACROBLOCK_MOTION_FORWARD 8 +#define MACROBLOCK_QUANT 16 +#define DCT_TYPE_INTERLACED 32 +/* motion_type */ +#define MOTION_TYPE_SHIFT 6 +#define MOTION_TYPE_MASK (3*64) +#define MOTION_TYPE_BASE 64 +#define MC_FIELD (1*64) +#define MC_FRAME (2*64) +#define MC_16X8 (2*64) +#define MC_DMV (3*64) + +/* picture structure */ +#define TOP_FIELD 1 +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +/* picture coding type */ +#define I_TYPE 1 +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +struct macroblock_8{ + unsigned char Y[16][16]; //0 + unsigned char Cb[8][8]; //1 + unsigned char Cr[8][8]; //2 +}; + +struct macroblock_16{ + short Y[16][16]; //0 + short Cb[8][8]; //1 + short Cr[8][8]; //2 +}; + +struct rgb32{ + unsigned char r, g, b, a; +}; + +struct macroblock_rgb32{ + struct rgb32 c[16][16]; +}; + +struct rgb16{ + unsigned short r:5, g:5, b:5, a:1; +}; + +struct macroblock_rgb16{ + struct rgb16 c[16][16]; +}; + +struct decoder_s { + /* first, state that carries information from one macroblock to the */ + /* next inside a slice, and is never used outside of mpeg2_slice() */ + + /* DCT coefficients - should be kept aligned ! */ + s16 DCTblock[64]; + + /* bit parsing stuff */ + u32 bitstream_buf; /* current 32 bit working set */ + int bitstream_bits; /* used bits in working set */ + u8 * bitstream_ptr; /* buffer with stream data; 128 bits buffer */ + + struct macroblock_8 *mb8; + struct macroblock_16 *mb16; + struct macroblock_rgb32 *rgb32; + struct macroblock_rgb16 *rgb16; + + int stride; + + /* predictor for DC coefficients in intra blocks */ + s16 dc_dct_pred[3]; + + int quantizer_scale; /* remove */ + int dmv_offset; /* remove */ + + /* now non-slice-specific information */ + + /* sequence header stuff */ + u8 *intra_quantizer_matrix; + u8 *non_intra_quantizer_matrix; + + /* picture header stuff */ + + /* what type of picture this is (I, P, B, D) */ + int coding_type; + + /* picture coding extension stuff */ + + /* quantization factor for intra dc coefficients */ + int intra_dc_precision; + /* top/bottom/both fields */ + int picture_structure; + /* bool to indicate all predictions are frame based */ + int frame_pred_frame_dct; + /* bool to indicate whether intra blocks have motion vectors */ + /* (for concealment) */ + int concealment_motion_vectors; + /* bit to indicate which quantization table to use */ + int q_scale_type; + /* bool to use different vlc tables */ + int intra_vlc_format; + /* used for DMV MC */ + int top_field_first; + // Pseudo Sign Offset + int sgn; + // Dither Enable + int dte; + // Output Format + int ofm; + // Macroblock count + int mbc; + // Macroblock type + int macroblock_modes; + // DC Reset + int dcr; + // Coded block pattern + int coded_block_pattern; + + /* stuff derived from bitstream */ + + /* pointer to the zigzag scan we're supposed to be using */ + const u8 * scan; + + int second_field; + + int mpeg1; +}; + +typedef struct decoder_s decoder_t; + +#define IDEC 0 +#define BDEC 1 +void mpeg2sliceIDEC(void* pdone); +void mpeg2_slice(void* pdone); +int get_macroblock_address_increment(decoder_t * const decoder); +int get_macroblock_modes (decoder_t * const decoder); +int get_motion_delta (decoder_t * const decoder, + const int f_code); +int get_dmv (decoder_t * const decoder); +int non_linear_quantizer_scale[]; // JayteeMaster: it is needed in Ipu.c + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn); +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte); +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4); +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16); + +int slice (decoder_t * const decoder, u8 * buffer); +/* idct.c */ +void mpeg2_idct_init (); + +#endif//__MPEG_H__ diff --git a/IPU/mpeg2lib/Vlc.h b/IPU/mpeg2lib/Vlc.h new file mode 100644 index 0000000000..ef8f43e7ce --- /dev/null +++ b/IPU/mpeg2lib/Vlc.h @@ -0,0 +1,441 @@ +/* + * vlc.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VLC_H__ +#define __VLC_H__ + +#include "IPU.h" +#include "pcl.h" + +static u8 data[2]; +static u8 dword[4]; +static void GETWORD(u32 * bit_buf,int bits) +{ + while(!getBits16(data,1)) + co_resume(); + *bit_buf |= ((data[0] << 8) | data[1]) << (bits); +} + +static void bitstream_init (decoder_t * decoder){ + decoder->bitstream_bits = -16; + + while( !getBits32(dword, 1) ) + co_resume(); + + decoder->bitstream_buf = (dword[0] << 24) | (dword[1] << 16) | + (dword[2] << 8) |dword[3]; +} + +/* make sure that there are at least 16 valid bits in bit_buf */ +#define NEEDBITS(bit_buf,bits,bit_ptr) \ +do { \ + if (bits > 0) { \ + GETWORD(&bit_buf,bits); \ + bits -= 16; \ + } \ +} while (0) + +/* remove num valid bits from bit_buf */ +#define DUMPBITS(bit_buf,bits,num) \ +do { \ + /*IPU_LOG("DUMPBITS %d\n",num);*/ \ + bit_buf <<= (num); \ + bits += (num); \ +} while (0) + +/* take num bits from the high part of bit_buf and zero extend them */ +#define UBITS(bit_buf,num) (((u32)(bit_buf)) >> (32 - (num))) + +/* take num bits from the high part of bit_buf and sign extend them */ +#define SBITS(bit_buf,num) (((s32)(bit_buf)) >> (32 - (num))) + +typedef struct { + u8 modes; + u8 len; +} MBtab; + +typedef struct { + u8 delta; + u8 len; +} MVtab; + +typedef struct { + s8 dmv; + u8 len; +} DMVtab; + +typedef struct { + u8 cbp; + u8 len; +} CBPtab; + +typedef struct { + u8 size; + u8 len; +} DCtab; + +typedef struct { + u8 run; + u8 level; + u8 len; +} DCTtab; + +typedef struct { + u8 mba; + u8 len; +} MBAtab; + + +#define INTRA MACROBLOCK_INTRA +#define QUANT MACROBLOCK_QUANT + +static const MBtab MB_I [] = { + {INTRA|QUANT, 2}, {INTRA, 1} +}; + +#define MC MACROBLOCK_MOTION_FORWARD +#define CODED MACROBLOCK_PATTERN + +static const MBtab MB_P [] = { + {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, + {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} +}; + +#define FWD MACROBLOCK_MOTION_FORWARD +#define BWD MACROBLOCK_MOTION_BACKWARD +#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD + +static const MBtab MB_B [] = { + {0, 0}, {INTRA|QUANT, 6}, + {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, + {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, + {INTRA, 5}, {INTRA, 5}, + {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, + {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} +}; + +#undef INTRA +#undef QUANT +#undef MC +#undef CODED +#undef FWD +#undef BWD +#undef INTER + + +static const MVtab MV_4 [] = { + { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} +}; + +static const MVtab MV_10 [] = { + { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, + { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, + {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, + { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, + { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, + { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} +}; + + +static const DMVtab DMV_2 [] = { + { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} +}; + + +static const CBPtab CBP_7 [] = { + {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7}, + {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7}, + {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6}, + {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6}, + {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, + {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5}, + {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, + {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5}, + {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5}, + {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5}, + {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, + {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, + {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5}, + {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5}, + {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5}, + {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3} +}; + +static const CBPtab CBP_9 [] = { + {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9}, + {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9}, + {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8}, + {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8}, + {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8}, + {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8}, + {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8}, + {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8}, + {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8}, + {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8}, + {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8}, + {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8}, + {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8}, + {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8}, + {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8}, + {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8} +}; + +static const DCtab DC_lum_5 [] = { + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} +}; + +static const DCtab DC_chrom_5 [] = { + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} +}; + +static const DCtab DC_long [] = { + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} +}; + + +static const DCTtab DCT_16 [] = { + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, + { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, + { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, + { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} +}; + +static const DCTtab DCT_15 [] = { + { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, + { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, + { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, + { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, + { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, + { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, + { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, + { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, + { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, + { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, + { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, + { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} +}; + +static const DCTtab DCT_13 [] = { + { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, + { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, + { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, + { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, + { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, + { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, + { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, + { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, + { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, + { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, + { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, + { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} +}; + +static const DCTtab DCT_B14_10 [] = { + { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, + { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} +}; + +static const DCTtab DCT_B14_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, + { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, + { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, + { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, + { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} +}; + +static const DCTtab DCT_B14AC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} +}; + +static const DCTtab DCT_B14DC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} +}; + +static const DCTtab DCT_B15_10 [] = { + { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, + { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} +}; + +static const DCTtab DCT_B15_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, + { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, + { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, + { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, + { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, + { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, + { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, + { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} +}; + + +static const MBAtab MBA_5 [] = { + {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} +}; + +static const MBAtab MBA_11 [] = { + {32, 11}, {31, 11}, {30, 11}, {29, 11}, + {28, 11}, {27, 11}, {26, 11}, {25, 11}, + {24, 11}, {23, 11}, {22, 11}, {21, 11}, + {20, 10}, {20, 10}, {19, 10}, {19, 10}, + {18, 10}, {18, 10}, {17, 10}, {17, 10}, + {16, 10}, {16, 10}, {15, 10}, {15, 10}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} +}; +#endif//__VLC_H__ diff --git a/IPU/yuv2rgb.c b/IPU/yuv2rgb.c new file mode 100644 index 0000000000..17d6c0c29b --- /dev/null +++ b/IPU/yuv2rgb.c @@ -0,0 +1,510 @@ +/* + * yuv2rgb.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +//#include "convert_internal.h" //START +typedef struct { + u8 * rgb_ptr; + int width; + int uv_stride, uv_stride_frame; + int rgb_stride, rgb_stride_frame; + void (* yuv2rgb) (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); +} convert_rgb_t; + +typedef void yuv2rgb_copy (void * id, u8 * const * src, + unsigned int v_offset); + +yuv2rgb_copy * yuv2rgb_init_mmxext (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mmx (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mlib (int bpp, int mode); +//#include "convert_internal.h" //END + +static u32 matrix_coefficients = 6; + +const s32 Inverse_Table_6_9[8][4] = { + {117504, 138453, 13954, 34903}, /*0 no sequence_display_extension */ + {117504, 138453, 13954, 34903}, /*1 ITU-R Rec. 709 (1990) */ + {104597, 132201, 25675, 53279}, /*2 unspecified */ + {104597, 132201, 25675, 53279}, /*3 reserved */ + {104448, 132798, 24759, 53109}, /*4 FCC */ + {104597, 132201, 25675, 53279}, /*5 ITU-R Rec. 624-4 System B, G */ + {104597, 132201, 25675, 53279}, /*6 SMPTE 170M */ + {117579, 136230, 16907, 35559} /*7 SMPTE 240M (1987) */ +}; + +typedef void yuv2rgb_c_internal (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); + +void * table_rV[256]; +void * table_gU[256]; +int table_gV[256]; +void * table_bU[256]; + +#define _RGB(type,i) \ + U = pu[i]; \ + V = pv[i]; \ + r = (type *) table_rV[V]; \ + g = (type *) (((u8 *)table_gU[U]) + table_gV[V]); \ + b = (type *) table_bU[U]; + +#define DST(py,dst,i) \ + Y = py[2*i]; \ + dst[2*i] = r[Y] + g[Y] + b[Y]; \ + Y = py[2*i+1]; \ + dst[2*i+1] = r[Y] + g[Y] + b[Y]; + +#define DSTRGB(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = r[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = b[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = r[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = b[Y]; + +#define DSTBGR(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = b[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = r[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = b[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = r[Y]; + +static void yuv2rgb_c_32 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u32 * r, * g, * b; + u32 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u32 *) _dst_1; + dst_2 = (u32 *) _dst_2; + + do { + _RGB (u32, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u32, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u32, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u32, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +/* This is very near from the yuv2rgb_c_32 code */ +static void yuv2rgb_c_24_rgb (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTRGB (py_1, dst_1, 0); + DSTRGB (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTRGB (py_2, dst_2, 1); + DSTRGB (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTRGB (py_1, dst_1, 2); + DSTRGB (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTRGB (py_2, dst_2, 3); + DSTRGB (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* only trivial mods from yuv2rgb_c_24_rgb */ +static void yuv2rgb_c_24_bgr (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTBGR (py_1, dst_1, 0); + DSTBGR (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTBGR (py_2, dst_2, 1); + DSTBGR (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTBGR (py_1, dst_1, 2); + DSTBGR (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTBGR (py_2, dst_2, 3); + DSTBGR (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ +/* r, g, b, dst_1, dst_2 */ +static void yuv2rgb_c_16 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u16 * r, * g, * b; + u16 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u16 *) _dst_1; + dst_2 = (u16 *) _dst_2; + + do { + _RGB (u16, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u16, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u16, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u16, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +static int div_round (int dividend, int divisor) +{ + if (dividend > 0) + return (dividend + (divisor>>1)) / divisor; + else + return -((-dividend + (divisor>>1)) / divisor); +} + +static yuv2rgb_c_internal * yuv2rgb_c_init (int order, int bpp) +{ + int i; + u8 table_Y[1024]; + u32 * table_32 = 0; + u16 * table_16 = 0; + u8 * table_8 = 0; + int entry_size = 0; + void * table_r = 0; + void * table_g = 0; + void * table_b = 0; + yuv2rgb_c_internal * yuv2rgb; + + int crv = Inverse_Table_6_9[matrix_coefficients][0]; + int cbu = Inverse_Table_6_9[matrix_coefficients][1]; + int cgu = -Inverse_Table_6_9[matrix_coefficients][2]; + int cgv = -Inverse_Table_6_9[matrix_coefficients][3]; + + for (i = 0; i < 1024; i++) { + int j; + + j = (76309 * (i - 384 - 16) + 32768) >> 16; + j = (j < 0) ? 0 : ((j > 255) ? 255 : j); + table_Y[i] = j; + } + + switch (bpp) { + case 32: + yuv2rgb = yuv2rgb_c_32; + + table_32 = (u32 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u32)); + + entry_size = sizeof (u32); + table_r = table_32 + 197; + table_b = table_32 + 197 + 685; + table_g = table_32 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) + ((u32 *) table_r)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 16 : 0); + for (i = -132; i < 256+132; i++) + ((u32 *) table_g)[i] = table_Y[i+384] << 8; + for (i = -232; i < 256+232; i++) + ((u32 *) table_b)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 0 : 16); + break; + + case 24: + yuv2rgb = (order == CONVERT_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; + + table_8 = (u8 *) malloc ((256 + 2*232) * sizeof (u8)); + + entry_size = sizeof (u8); + table_r = table_g = table_b = table_8 + 232; + + for (i = -232; i < 256+232; i++) + ((u8 * )table_b)[i] = table_Y[i+384]; + break; + + case 15: + case 16: + yuv2rgb = yuv2rgb_c_16; + + table_16 = (u16 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u16)); + + entry_size = sizeof (u16); + table_r = table_16 + 197; + table_b = table_16 + 197 + 685; + table_g = table_16 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_r)[i] = j; + } + for (i = -132; i < 256+132; i++) { + int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3); + + ((u16 *)table_g)[i] = j << 5; + } + for (i = -232; i < 256+232; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_b)[i] = j; + } + break; + + default: + fprintf (stderr, "%ibpp not supported by yuv2rgb\n", bpp); + exit (1); + } + + for (i = 0; i < 256; i++) { + table_rV[i] = (((u8 *)table_r) + + entry_size * div_round (crv * (i-128), 76309)); + table_gU[i] = (((u8 *)table_g) + + entry_size * div_round (cgu * (i-128), 76309)); + table_gV[i] = entry_size * div_round (cgv * (i-128), 76309); + table_bU[i] = (((u8 *)table_b) + + entry_size * div_round (cbu * (i-128), 76309)); + } + + return yuv2rgb; +} + +static void convert_yuv2rgb_c (void * _id, u8 * Y, u8 * Cr, u8 * Cb, + unsigned int v_offset) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + u8 * dst; + u8 * py; + u8 * pu; + u8 * pv; + int loop; + + dst = id->rgb_ptr + id->rgb_stride * v_offset; + py = Y; pu = Cr; pv = Cb; + + loop = 8; + do { + id->yuv2rgb (py, py + (id->uv_stride << 1), pu, pv, + dst, dst + id->rgb_stride, id->width); + py += id->uv_stride << 2; + pu += id->uv_stride; + pv += id->uv_stride; + dst += 2 * id->rgb_stride; + } while (--loop); +} + +static void convert_start (void * _id, u8 * dest, int flags) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + id->rgb_ptr = dest; + switch (flags) { + case CONVERT_BOTTOM_FIELD: + id->rgb_ptr += id->rgb_stride_frame; + /* break thru */ + case CONVERT_TOP_FIELD: + id->uv_stride = id->uv_stride_frame << 1; + id->rgb_stride = id->rgb_stride_frame << 1; + break; + default: + id->uv_stride = id->uv_stride_frame; + id->rgb_stride = id->rgb_stride_frame; + } +} + +static void convert_internal (int order, int bpp, int width, int height, + u32 accel, void * arg, + convert_init_t * result) +{ + convert_rgb_t * id = (convert_rgb_t *) result->id; + + if (!id) { + result->id_size = sizeof (convert_rgb_t); + } else { + id->width = width; + id->uv_stride_frame = width >> 1; + id->rgb_stride_frame = ((bpp + 7) >> 3) * width; + + result->buf_size[0] = id->rgb_stride_frame * height; + result->buf_size[1] = result->buf_size[2] = 0; + result->start = convert_start; + + result->copy = NULL; +#ifdef ARCH_X86 + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMXEXT)) { + result->copy = yuv2rgb_init_mmxext (order, bpp); + } + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMX)) { + result->copy = yuv2rgb_init_mmx (order, bpp); + } +#endif +#ifdef LIBVO_MLIB + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_MLIB)) { + result->copy = yuv2rgb_init_mlib (order, bpp); + } +#endif + if (result->copy == NULL) { + result->copy = convert_yuv2rgb_c; + id->yuv2rgb = yuv2rgb_c_init (order, bpp); + } + } +} + +void convert_rgb32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 32, width, height, accel, arg, result); +} + +void convert_rgb24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 24, width, height, accel, arg, result); +} + +void convert_rgb16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 16, width, height, accel, arg, result); +} + +void convert_rgb15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 15, width, height, accel, arg, result); +} + +void convert_bgr32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 32, width, height, accel, arg, result); +} + +void convert_bgr24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 24, width, height, accel, arg, result); +} + +void convert_bgr16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 16, width, height, accel, arg, result); +} + +void convert_bgr15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 15, width, height, accel, arg, result); +} + +convert_t* convert_rgb (int order, int bpp) +{ + if (order == CONVERT_RGB || order == CONVERT_BGR) + switch (bpp) { + case 32: return (order == CONVERT_RGB) ? convert_rgb32 : convert_bgr32; + case 24: return (order == CONVERT_RGB) ? convert_rgb24 : convert_bgr24; + case 16: return (order == CONVERT_RGB) ? convert_rgb16 : convert_bgr16; + case 15: return (order == CONVERT_RGB) ? convert_rgb15 : convert_bgr15; + } + return NULL; +} diff --git a/IPU/yuv2rgb.h b/IPU/yuv2rgb.h new file mode 100644 index 0000000000..d9d4d9ccd4 --- /dev/null +++ b/IPU/yuv2rgb.h @@ -0,0 +1,57 @@ +/* + * yuv2rgb.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef YUV2RGB_H +#define YUV2RGB_H + +#define CONVERT_FRAME 0 +#define CONVERT_TOP_FIELD 1 +#define CONVERT_BOTTOM_FIELD 2 +#define CONVERT_BOTH_FIELDS 3 + +typedef struct convert_init_s { + void * id; + int id_size; + int buf_size[3]; + void (* start) (void * id, u8 * dest, int flags); + void (* copy) (void * id, u8 * Y, u8 * Cr, u8 * Cb, unsigned int v_offset); +} convert_init_t; + +typedef void convert_t (int width, int height, u32 accel, void * arg, + convert_init_t * result); + +convert_t convert_rgb32; +convert_t convert_rgb24; +convert_t convert_rgb16; +convert_t convert_rgb15; +convert_t convert_bgr32; +convert_t convert_bgr24; +convert_t convert_bgr16; +convert_t convert_bgr15; + +#define CONVERT_RGB 0 +#define CONVERT_BGR 1 +convert_t * convert_rgb (int order, int bpp); + +#endif /* YUV2RGB_H */ diff --git a/InterTables.c b/InterTables.c new file mode 100644 index 0000000000..5f79905ff3 --- /dev/null +++ b/InterTables.c @@ -0,0 +1,224 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//all tables for R5900 are define here.. + +#include "InterTables.h" + +void (*Int_OpcodePrintTable[64])() = +{ + SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, + ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, + COP0, COP1, COP2, UnknownOpcode, BEQL, BNEL, BLEZL, BGTZL, + DADDI, DADDIU, LDL, LDR, MMI, UnknownOpcode, LQ, SQ, + LB, LH, LWL, LW, LBU, LHU, LWR, LWU, + SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, + UnknownOpcode, LWC1, UnknownOpcode, PREF, UnknownOpcode,UnknownOpcode, LQC2, LD, + UnknownOpcode, SWC1, UnknownOpcode, UnknownOpcode, UnknownOpcode,UnknownOpcode, SQC2, SD +}; + + +void (*Int_SpecialPrintTable[64])() = +{ + SLL, UnknownOpcode, SRL, SRA, SLLV, UnknownOpcode, SRLV, SRAV, + JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, UnknownOpcode, SYNC, + MFHI, MTHI, MFLO, MTLO, DSLLV, UnknownOpcode, DSRLV, DSRAV, + MULT, MULTU, DIV, DIVU, UnknownOpcode,UnknownOpcode,UnknownOpcode,UnknownOpcode, + ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, + MFSA , MTSA , SLT, SLTU, DADD, DADDU, DSUB, DSUBU, + TGE, TGEU, TLT, TLTU, TEQ, UnknownOpcode, TNE, UnknownOpcode, + DSLL, UnknownOpcode, DSRL, DSRA, DSLL32, UnknownOpcode, DSRL32, DSRA32 +}; + +void (*Int_REGIMMPrintTable[32])() = { + BLTZ, BGEZ, BLTZL, BGEZL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + TGEI, TGEIU, TLTI, TLTIU, TEQI, UnknownOpcode, TNEI, UnknownOpcode, + BLTZAL, BGEZAL, BLTZALL, BGEZALL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + MTSAB, MTSAH , UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, +}; + +void (*Int_MMIPrintTable[64])() = +{ + MADD, MADDU, MMI_Unknown, MMI_Unknown, PLZCW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI0, MMI2, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MFHI1, MTHI1, MFLO1, MTLO1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MULT1, MULTU1, DIV1, DIVU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MADD1, MADDU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI1 , MMI3, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHL, PMTHL, MMI_Unknown, MMI_Unknown, PSLLH, MMI_Unknown, PSRLH, PSRAH, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, PSLLW, MMI_Unknown, PSRLW, PSRAW, +}; + +void (*Int_MMI0PrintTable[32])() = +{ + PADDW, PSUBW, PCGTW, PMAXW, + PADDH, PSUBH, PCGTH, PMAXH, + PADDB, PSUBB, PCGTB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDSW, PSUBSW, PEXTLW, PPACW, + PADDSH, PSUBSH, PEXTLH, PPACH, + PADDSB, PSUBSB, PEXTLB, PPACB, + MMI_Unknown, MMI_Unknown, PEXT5, PPAC5, +}; + +void (*Int_MMI1PrintTable[32])() = +{ + MMI_Unknown, PABSW, PCEQW, PMINW, + PADSBH, PABSH, PCEQH, PMINH, + MMI_Unknown, MMI_Unknown, PCEQB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDUW, PSUBUW, PEXTUW, MMI_Unknown, + PADDUH, PSUBUH, PEXTUH, MMI_Unknown, + PADDUB, PSUBUB, PEXTUB, QFSRV, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, +}; + + +void (*Int_MMI2PrintTable[32])() = +{ + PMADDW, MMI_Unknown, PSLLVW, PSRLVW, + PMSUBW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHI, PMFLO, PINTH, MMI_Unknown, + PMULTW, PDIVW, PCPYLD, MMI_Unknown, + PMADDH, PHMADH, PAND, PXOR, + PMSUBH, PHMSBH, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXEH, PREVH, + PMULTH, PDIVBW, PEXEW, PROT3W, +}; + +void (*Int_MMI3PrintTable[32])() = +{ + PMADDUW, MMI_Unknown, MMI_Unknown, PSRAVW, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMTHI, PMTLO, PINTEH, MMI_Unknown, + PMULTUW, PDIVUW, PCPYUD, MMI_Unknown, + MMI_Unknown, MMI_Unknown, POR, PNOR, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXCH, PCPYH, + MMI_Unknown, MMI_Unknown, PEXCW, MMI_Unknown, +}; + +void (*Int_COP0PrintTable[32])() = +{ + MFC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, MTC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_BC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Func, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0BC0PrintTable[32])() = +{ + BC0F, BC0T, BC0FL, BC0TL, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0C0PrintTable[64])() = { + COP0_Unknown, TLBR, TLBWI, COP0_Unknown, COP0_Unknown, COP0_Unknown, TLBWR, COP0_Unknown, + TLBP, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + ERET, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + EI, DI, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown +}; + +void (*Int_COP1PrintTable[32])() = { + MFC1, COP1_Unknown, CFC1, COP1_Unknown, MTC1, COP1_Unknown, CTC1, COP1_Unknown, + COP1_BC1, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_S, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_W, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1BC1PrintTable[32])() = { + BC1F, BC1T, BC1FL, BC1TL, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1SPrintTable[64])() = { +ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,RSQRT_S, COP1_Unknown, +ADDA_S, SUBA_S, MULA_S, COP1_Unknown,MADD_S, MSUB_S, MADDA_S, MSUBA_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,CVT_W, COP1_Unknown,COP1_Unknown,COP1_Unknown, +MAX_S, MIN_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +C_F, COP1_Unknown,C_EQ, COP1_Unknown,C_LT, COP1_Unknown,C_LE, COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + +void (*Int_COP1WPrintTable[64])() = { +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +CVT_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + + +void (*Int_COP2PrintTable[32])() = { + COP2_Unknown, QMFC2, CFC2, COP2_Unknown, COP2_Unknown, QMTC2, CTC2, COP2_Unknown, + COP2_BC2, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, +}; + +void (*Int_COP2BC2PrintTable[32])() = { + BC2F, BC2T, BC2FL, BC2TL, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, +}; + +void (*Int_COP2SPECIAL1PrintTable[64])() = +{ + VADDx, VADDy, VADDz, VADDw, VSUBx, VSUBy, VSUBz, VSUBw, + VMADDx, VMADDy, VMADDz, VMADDw, VMSUBx, VMSUBy, VMSUBz, VMSUBw, + VMAXx, VMAXy, VMAXz, VMAXw, VMINIx, VMINIy, VMINIz, VMINIw, + VMULx, VMULy, VMULz, VMULw, VMULq, VMAXi, VMULi, VMINIi, + VADDq, VMADDq, VADDi, VMADDi, VSUBq, VMSUBq, VSUBi, VMSUBi, + VADD, VMADD, VMUL, VMAX, VSUB, VMSUB, VOPMSUB, VMINI, + VIADD, VISUB, VIADDI, COP2_Unknown,VIAND, VIOR, COP2_Unknown, COP2_Unknown, + VCALLMS, VCALLMSR, COP2_Unknown,COP2_Unknown,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2, +}; + +void (*Int_COP2SPECIAL2PrintTable[128])() = +{ + VADDAx ,VADDAy ,VADDAz ,VADDAw ,VSUBAx ,VSUBAy ,VSUBAz ,VSUBAw, + VMADDAx ,VMADDAy ,VMADDAz ,VMADDAw ,VMSUBAx ,VMSUBAy ,VMSUBAz ,VMSUBAw, + VITOF0 ,VITOF4 ,VITOF12 ,VITOF15 ,VFTOI0 ,VFTOI4 ,VFTOI12 ,VFTOI15, + VMULAx ,VMULAy ,VMULAz ,VMULAw ,VMULAq ,VABS ,VMULAi ,VCLIPw, + VADDAq ,VMADDAq ,VADDAi ,VMADDAi ,VSUBAq ,VMSUBAq ,VSUBAi ,VMSUBAi, + VADDA ,VMADDA ,VMULA ,COP2_Unknown,VSUBA ,VMSUBA ,VOPMULA ,VNOP, + VMOVE ,VMR32 ,COP2_Unknown,COP2_Unknown,VLQI ,VSQI ,VLQD ,VSQD, + VDIV ,VSQRT ,VRSQRT ,VWAITQ ,VMTIR ,VMFIR ,VILWR ,VISWR, + VRNEXT ,VRGET ,VRINIT ,VRXOR ,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, +}; diff --git a/InterTables.h b/InterTables.h new file mode 100644 index 0000000000..5788826334 --- /dev/null +++ b/InterTables.h @@ -0,0 +1,491 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef INTERTABLES_H +#define INTERTABLES_H + +extern void (*Int_OpcodePrintTable[64])(); +extern void (*Int_SpecialPrintTable[64])(); +extern void (*Int_REGIMMPrintTable[32])(); +extern void (*Int_MMIPrintTable[64])(); +extern void (*Int_MMI0PrintTable[32])(); +extern void (*Int_MMI1PrintTable[32])(); +extern void (*Int_MMI2PrintTable[32])(); +extern void (*Int_MMI3PrintTable[32])(); +extern void (*Int_COP0PrintTable[32])(); +extern void (*Int_COP0BC0PrintTable[32])(); +extern void (*Int_COP0C0PrintTable[64])(); +extern void (*Int_COP1PrintTable[32])(); +extern void (*Int_COP1BC1PrintTable[32])(); +extern void (*Int_COP1SPrintTable[64])(); +extern void (*Int_COP1WPrintTable[64])(); +extern void (*Int_COP2PrintTable[32])(); +extern void (*Int_COP2BC2PrintTable[32])(); +extern void (*Int_COP2SPECIAL1PrintTable[64])(); +extern void (*Int_COP2SPECIAL2PrintTable[128])(); + +void SPECIAL(); +void REGIMM(); +void UnknownOpcode(); +void COP0(); +void COP1(); +void COP2(); +void MMI_Unknown(); +void MMI(); +void MMI0(); +void MMI1(); +void MMI2(); +void MMI3(); +void COP0_Unknown(); +void COP0_BC0(); +void COP0_Func(); +void COP1_BC1(); +void COP1_S(); +void COP1_W(); +void COP1_Unknown(); +void COP2_BC2(); +void COP2_SPECIAL(); +void COP2_Unknown(); +void COP2_SPECIAL2(); + +// **********************Standard Opcodes************************** +void J(); +void JAL(); +void BEQ(); +void BNE(); +void BLEZ(); +void BGTZ(); +void ADDI(); +void ADDIU(); +void SLTI(); +void SLTIU(); +void ANDI(); +void ORI(); +void XORI(); +void LUI(); +void BEQL(); +void BNEL(); +void BLEZL(); +void BGTZL(); +void DADDI(); +void DADDIU(); +void LDL(); +void LDR(); +void LB(); +void LH(); +void LWL(); +void LW(); +void LBU(); +void LHU(); +void LWR(); +void LWU(); +void SB(); +void SH(); +void SWL(); +void SW(); +void SDL(); +void SDR(); +void SWR(); +void CACHE(); +void LWC1(); +void PREF(); +void LQC2(); +void LD(); +void SQC2(); +void SD(); +void LQ(); +void SQ(); +void SWC1(); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void SLL(); +void SRL(); +void SRA(); +void SLLV(); +void SRLV(); +void SRAV(); +void JR(); +void JALR(); +void SYSCALL(); +void BREAK(); +void SYNC(); +void MFHI(); +void MTHI(); +void MFLO(); +void MTLO(); +void DSLLV(); +void DSRLV(); +void DSRAV(); +void MULT(); +void MULTU(); +void DIV(); +void DIVU(); +void ADD(); +void ADDU(); +void SUB(); +void SUBU(); +void AND(); +void OR(); +void XOR(); +void NOR(); +void SLT(); +void SLTU(); +void DADD(); +void DADDU(); +void DSUB(); +void DSUBU(); +void TGE(); +void TGEU(); +void TLT(); +void TLTU(); +void TEQ(); +void TNE(); +void DSLL(); +void DSRL(); +void DSRA(); +void DSLL32(); +void DSRL32(); +void DSRA32(); +void MOVZ(); +void MOVN(); +void MFSA(); +void MTSA(); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void BLTZ(); +void BGEZ(); +void BLTZL(); +void BGEZL(); +void TGEI(); +void TGEIU(); +void TLTI(); +void TLTIU(); +void TEQI(); +void TNEI(); +void BLTZAL(); +void BGEZAL(); +void BLTZALL(); +void BGEZALL(); +void MTSAB(); +void MTSAH(); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void MADD(); +void MADDU(); +void PLZCW(); +void MADD1(); +void MADDU1(); +void MFHI1(); +void MTHI1(); +void MFLO1(); +void MTLO1(); +void MULT1(); +void MULTU1(); +void DIV1(); +void DIVU1(); +void PMFHL(); +void PMTHL(); +void PSLLH(); +void PSRLH(); +void PSRAH(); +void PSLLW(); +void PSRLW(); +void PSRAW(); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void PADDW(); +void PSUBW(); +void PCGTW(); +void PMAXW(); +void PADDH(); +void PSUBH(); +void PCGTH(); +void PMAXH(); +void PADDB(); +void PSUBB(); +void PCGTB(); +void PADDSW(); +void PSUBSW(); +void PEXTLW(); +void PPACW(); +void PADDSH(); +void PSUBSH(); +void PEXTLH(); +void PPACH(); +void PADDSB(); +void PSUBSB(); +void PEXTLB(); +void PPACB(); +void PEXT5(); +void PPAC5(); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void PABSW(); +void PCEQW(); +void PMINW(); +void PADSBH(); +void PABSH(); +void PCEQH(); +void PMINH(); +void PCEQB(); +void PADDUW(); +void PSUBUW(); +void PEXTUW(); +void PADDUH(); +void PSUBUH(); +void PEXTUH(); +void PADDUB(); +void PSUBUB(); +void PEXTUB(); +void QFSRV(); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void PMADDW(); +void PSLLVW(); +void PSRLVW(); +void PMSUBW(); +void PMFHI(); +void PMFLO(); +void PINTH(); +void PMULTW(); +void PDIVW(); +void PCPYLD(); +void PMADDH(); +void PHMADH(); +void PAND(); +void PXOR(); +void PMSUBH(); +void PHMSBH(); +void PEXEH(); +void PREVH(); +void PMULTH(); +void PDIVBW(); +void PEXEW(); +void PROT3W(); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void PMADDUW(); +void PSRAVW(); +void PMTHI(); +void PMTLO(); +void PINTEH(); +void PMULTUW(); +void PDIVUW(); +void PCPYUD(); +void POR(); +void PNOR(); +void PEXCH(); +void PCPYH(); +void PEXCW(); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void MFC0(); +void MTC0(); +void BC0F(); +void BC0T(); +void BC0FL(); +void BC0TL(); +void TLBR(); +void TLBWI(); +void TLBWR(); +void TLBP(); +void ERET(); +void DI(); +void EI(); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void MFC1(); +void CFC1(); +void MTC1(); +void CTC1(); +void BC1F(); +void BC1T(); +void BC1FL(); +void BC1TL(); +void ADD_S(); +void SUB_S(); +void MUL_S(); +void DIV_S(); +void SQRT_S(); +void ABS_S(); +void MOV_S(); +void NEG_S(); +void RSQRT_S(); +void ADDA_S(); +void SUBA_S(); +void MULA_S(); +void MADD_S(); +void MSUB_S(); +void MADDA_S(); +void MSUBA_S(); +void CVT_W(); +void MAX_S(); +void MIN_S(); +void C_F(); +void C_EQ(); +void C_LT(); +void C_LE(); + void CVT_S(); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void QMFC2(); +void CFC2(); +void QMTC2(); +void CTC2(); +void BC2F(); +void BC2T(); +void BC2FL(); +void BC2TL(); +//*****************SPECIAL 1 VUO TABLE******************************* +void VADDx(); +void VADDy(); +void VADDz(); +void VADDw(); +void VSUBx(); +void VSUBy(); +void VSUBz(); +void VSUBw(); +void VMADDx(); +void VMADDy(); +void VMADDz(); +void VMADDw(); +void VMSUBx(); +void VMSUBy(); +void VMSUBz(); +void VMSUBw(); +void VMAXx(); +void VMAXy(); +void VMAXz(); +void VMAXw(); +void VMINIx(); +void VMINIy(); +void VMINIz(); +void VMINIw(); +void VMULx(); +void VMULy(); +void VMULz(); +void VMULw(); +void VMULq(); +void VMAXi(); +void VMULi(); +void VMINIi(); +void VADDq(); +void VMADDq(); +void VADDi(); +void VMADDi(); +void VSUBq(); +void VMSUBq(); +void VSUBi(); +void VMSUBi(); +void VADD(); +void VMADD(); +void VMUL(); +void VMAX(); +void VSUB(); +void VMSUB(); +void VOPMSUB(); +void VMINI(); +void VIADD(); +void VISUB(); +void VIADDI(); +void VIAND(); +void VIOR(); +void VCALLMS(); +void VCALLMSR(); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void VADDAx(); +void VADDAy(); +void VADDAz(); +void VADDAw(); +void VSUBAx(); +void VSUBAy(); +void VSUBAz(); +void VSUBAw(); +void VMADDAx(); +void VMADDAy(); +void VMADDAz(); +void VMADDAw(); +void VMSUBAx(); +void VMSUBAy(); +void VMSUBAz(); +void VMSUBAw(); +void VITOF0(); +void VITOF4(); +void VITOF12(); +void VITOF15(); +void VFTOI0(); +void VFTOI4(); +void VFTOI12(); +void VFTOI15(); +void VMULAx(); +void VMULAy(); +void VMULAz(); +void VMULAw(); +void VMULAq(); +void VABS(); +void VMULAi(); +void VCLIPw(); +void VADDAq(); +void VMADDAq(); +void VADDAi(); +void VMADDAi(); +void VSUBAq(); +void VMSUBAq(); +void VSUBAi(); +void VMSUBAi(); +void VADDA(); +void VMADDA(); +void VMULA(); +void VSUBA(); +void VMSUBA(); +void VOPMULA(); +void VNOP(); +void VMOVE(); +void VMR32(); +void VLQI(); +void VSQI(); +void VLQD(); +void VSQD(); +void VDIV(); +void VSQRT(); +void VRSQRT(); +void VWAITQ(); +void VMTIR(); +void VMFIR(); +void VILWR(); +void VISWR(); +void VRNEXT(); +void VRGET(); +void VRINIT(); +void VRXOR(); +//************************************END OF SPECIAL2 ************ +#endif diff --git a/Interpreter.c b/Interpreter.c new file mode 100644 index 0000000000..10d4aa8f57 --- /dev/null +++ b/Interpreter.c @@ -0,0 +1,1072 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "ix86/ix86.h" + +#include + +extern u32 maxrecmem; + +char *bios[256]={ +//0x00 + "RFU000_FullReset", "ResetEE", "SetGsCrt", "RFU003", + "Exit", "RFU005", "LoadExecPS2", "ExecPS2", + "RFU008", "RFU009", "AddSbusIntcHandler", "RemoveSbusIntcHandler", + "Interrupt2Iop", "SetVTLBRefillHandler", "SetVCommonHandler", "SetVInterruptHandler", +//0x10 + "AddIntcHandler", "RemoveIntcHandler", "AddDmacHandler", "RemoveDmacHandler", + "_EnableIntc", "_DisableIntc", "_EnableDmac", "_DisableDmac", + "_SetAlarm", "_ReleaseAlarm", "_iEnableIntc", "_iDisableIntc", + "_iEnableDmac", "_iDisableDmac", "_iSetAlarm", "_iReleaseAlarm", +//0x20 + "CreateThread", "DeleteThread", "StartThread", "ExitThread", + "ExitDeleteThread", "TerminateThread", "iTerminateThread", "DisableDispatchThread", + "EnableDispatchThread", "ChangeThreadPriority", "iChangeThreadPriority", "RotateThreadReadyQueue", + "iRotateThreadReadyQueue", "ReleaseWaitThread", "iReleaseWaitThread", "GetThreadId", +//0x30 + "ReferThreadStatus","iReferThreadStatus", "SleepThread", "WakeupThread", + "_iWakeupThread", "CancelWakeupThread", "iCancelWakeupThread", "SuspendThread", + "iSuspendThread", "ResumeThread", "iResumeThread", "JoinThread", + "RFU060", "RFU061", "EndOfHeap", "RFU063", +//0x40 + "CreateSema", "DeleteSema", "SignalSema", "iSignalSema", + "WaitSema", "PollSema", "iPollSema", "ReferSemaStatus", + "iReferSemaStatus", "RFU073", "SetOsdConfigParam", "GetOsdConfigParam", + "GetGsHParam", "GetGsVParam", "SetGsHParam", "SetGsVParam", +//0x50 + "RFU080_CreateEventFlag", "RFU081_DeleteEventFlag", + "RFU082_SetEventFlag", "RFU083_iSetEventFlag", + "RFU084_ClearEventFlag", "RFU085_iClearEventFlag", + "RFU086_WaitEventFlag", "RFU087_PollEventFlag", + "RFU088_iPollEventFlag", "RFU089_ReferEventFlagStatus", + "RFU090_iReferEventFlagStatus", "RFU091_GetEntryAddress", + "EnableIntcHandler_iEnableIntcHandler", + "DisableIntcHandler_iDisableIntcHandler", + "EnableDmacHandler_iEnableDmacHandler", + "DisableDmacHandler_iDisableDmacHandler", +//0x60 + "KSeg0", "EnableCache", "DisableCache", "GetCop0", + "FlushCache", "RFU101", "CpuConfig", "iGetCop0", + "iFlushCache", "RFU105", "iCpuConfig", "sceSifStopDma", + "SetCPUTimerHandler", "SetCPUTimer", "SetOsdConfigParam2", "SetOsdConfigParam2", +//0x70 + "GsGetIMR_iGsGetIMR", "GsGetIMR_iGsPutIMR", "SetPgifHandler", "SetVSyncFlag", + "RFU116", "print", "sceSifDmaStat_isceSifDmaStat", "sceSifSetDma_isceSifSetDma", + "sceSifSetDChain_isceSifSetDChain", "sceSifSetReg", "sceSifGetReg", "ExecOSD", + "Deci2Call", "PSMode", "MachineType", "GetMemorySize", +}; + +extern void (*LT_OpcodePrintTable[64])(); +int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef CPU_LOG +#define debugI() \ + if (Log) { CPU_LOG("%s\n", disR5900F(cpuRegs.code, pc)); } \ + if (cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1]) SysPrintf("R0 is not zero!!!!\n"); +#else +#define debugI() +#endif +#define addcycles() + /*EEsCycle += cpuRegs.cycle - EEoCycle; \ + EEoCycle = cpuRegs.cycle;*/ + +extern void ExecuteIOP(); +u32 IOPtimer = 0; + +void execI() { + u32 pc = cpuRegs.pc; + + + //////////////////////////////////////////////////////// + /*if(IOPtimer >= 8) { + ExecuteIOP(); + IOPtimer = 0; + } + + IOPtimer++; + */ + /////////////////////////////////////////////////////// + + cpuRegs.cycle++; + //cpuRegs.CP0.n.Count++; /*count every cycles.*/ + + if (memRead32(cpuRegs.pc, &cpuRegs.code) == -1) return; + + debugI(); + cpuRegs.pc+= 4; + Int_OpcodePrintTable[cpuRegs.code >> 26](); +} + +__inline void doBranch(u32 tar) { + branch2 = cpuRegs.branch = 1; + branchPC = tar; + execI(); + cpuRegs.branch = 0; + cpuRegs.pc = branchPC; + + addcycles(); + cpuBranchTest(); +} + +void intDoBranch(u32 target) { + doBranch(target); +} + +void intSetBranch() { + branch2 = 1; +} + +void SPECIAL() {Int_SpecialPrintTable[_Funct_]();} +void REGIMM() {Int_REGIMMPrintTable[_Rt_](); } + + +void UnknownOpcode() { +#ifdef CPU_LOG + CPU_LOG("%8.8lx: Unknown opcode called\n", cpuRegs.pc); +#endif +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void ADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed!!!! +void ADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed !!! +void DADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void DADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void ANDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & (s64)_ImmU_; } // Rt = Rs And Im +void ORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | (s64)_ImmU_; } // Rt = Rs Or Im +void XORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ (s64)_ImmU_; } // Rt = Rs Xor Im +void SLTI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < (s64)(_Imm_); } // Rt = Rs < Im (signed) +void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < (u64)(_Imm_); } // Rt = Rs < Im (unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void ADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt (Exception on Integer Overflow) +void ADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt +void DADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void DADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void SUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs - Rt (Exception on Integer Overflow) +void SUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0]; } // Rd = Rs - Rt +void DSUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0];} +void DSUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0]; } +void AND() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs And Rt +void OR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Or Rt +void XOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Xor Rt +void NOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] =~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); }// Rd = Rs Nor Rt +void SLT() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]; } // Rd = Rs < Rt (signed) +void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs < Rt (unsigned) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void J() { +#ifdef EMU_LOG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + doBranch(_JumpTarget_); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + +void JAL() { +#ifdef EMU_LOG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + _SetLink(31); doBranch(_JumpTarget_); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void JR() { +#ifdef EMU_LOG + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; + u32 pc = cpuRegs.pc; + int rs = _Rs_; +#endif + doBranch(cpuRegs.GPR.r[_Rs_].UL[0]); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); + if (rs == 31) JumpCheckSymRet(pc); +#endif +} + +void JALR() { + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; +#ifdef EMU_LOG + u32 pc = cpuRegs.pc; +#endif + + if (_Rd_) { _SetLink(_Rd_); } + doBranch(temp); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void DIV() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +void MULT() { //different in ps2... + s64 res = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +void MULTU() { //different in ps2.. + u64 res = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void LUI() { + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void MFHI() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; } // Rd = Hi +void MFLO() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void MTHI() { cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Hi = Rs +void MTLO() { cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Lo = Rs + + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void SLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << _Sa_); } // Rd = Rt << sa +void DSLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << _Sa_); } +void DSLL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (_Sa_+32));} +void SRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> _Sa_); } // Rd = Rt >> sa (arithmetic) +void DSRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> _Sa_); } +void DSRA32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (_Sa_+32));} +void SRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> _Sa_); } // Rd = Rt >> sa (logical) +void DSRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> _Sa_); } +void DSRL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (_Sa_+32));} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void SLLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt << rs +void SRAV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (arithmetic) +void SRLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (logical) +void DSLLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRAV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) \ + if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \ + else {addcycles(); cpuBranchTest();} + + +void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else addcycles(); cpuBranchTest(); + +#define RepZBranchLinki32(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else addcycles(); cpuBranchTest(); + +void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void BGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void BLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void BLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; addcycles(); cpuBranchTest(); } + +#define RepZBranchLinki32Likely(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; addcycles(); cpuBranchTest(); } + +#define RepBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; addcycles(); cpuBranchTest(); } + + +void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt +void BNEL() { RepBranchi32Likely(!=) } // Branch if Rs != Rt +void BLEZL() { RepZBranchi32Likely(<=) } // Branch if Rs <= 0 +void BGTZL() { RepZBranchi32Likely(>) } // Branch if Rs > 0 +void BLTZL() { RepZBranchi32Likely(<) } // Branch if Rs < 0 +void BGEZL() { RepZBranchi32Likely(>=) } // Branch if Rs >= 0 +void BLTZALL() { RepZBranchLinki32Likely(<) } // Branch if Rs < 0 and link +void BGEZALL() { RepZBranchLinki32Likely(>=) } // Branch if Rs >= 0 and link + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void LB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RS(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead8RS(addr, &dummy); + } +} + +void LBU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RU(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead8RU(addr, &dummy); + } +} + +void LH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RS(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead16RS(addr, &dummy); + } +} + +void LHU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RU(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead16RU(addr, &dummy); + } +} + +void LW() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RS(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead32RS(addr, &dummy); + } +} + +void LWU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RU(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead32RU(addr, &dummy); + } +} + +u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; +u32 LWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void LWL() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWL_MASK[shift]) | + (mem << LWL_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + */ +} + +u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 }; +u32 LWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void LWR() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWR_MASK[shift]) | + (mem >> LWR_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + */ +} + +void LD() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead64(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead64(addr, &dummy); + } +} + +u64 LDL_MASK[8] = { 0x00ffffffffffffff, 0x0000ffffffffffff, 0x000000ffffffffff, 0x00000000ffffffff, + 0x0000000000ffffff, 0x000000000000ffff, 0x00000000000000ff, 0x0000000000000000 }; +u32 LDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void LDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDL_MASK[shift]) | + (mem << LDL_SHIFT[shift]); +} + +u64 LDR_MASK[8] = { 0x0000000000000000, 0xff00000000000000, 0xffff000000000000, 0xffffff0000000000, + 0xffffffff00000000, 0xffffffffff000000, 0xffffffffffff0000, 0xffffffffffffff00 }; +u32 LDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void LDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDR_MASK[shift]) | + (mem >> LDR_SHIFT[shift]); +} + +void LQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + + if (_Rt_) { + memRead128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +void SB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite8(addr, cpuRegs.GPR.r[_Rt_].UC[0]); +} + +void SH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite16(addr, cpuRegs.GPR.r[_Rt_].US[0]); +} + +void SW(){ + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); +} + +u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000 }; +u32 SWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void SWL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] >> SWL_SHIFT[shift]) | + ( mem & SWL_MASK[shift]) ); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + */ +} + +u32 SWR_MASK[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; +u32 SWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void SWR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] << SWR_SHIFT[shift]) | + ( mem & SWR_MASK[shift]) ); + + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + */ +} + +void SD() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite64(addr,cpuRegs.GPR.r[_Rt_].UD[0]); +} + +u64 SDL_MASK[8] = { 0xffffffffffffff00, 0xffffffffffff0000, 0xffffffffff000000, 0xffffffff00000000, + 0xffffff0000000000, 0xffff000000000000, 0xff00000000000000, 0x0000000000000000 }; +u32 SDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void SDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] >> SDL_SHIFT[shift]) | + ( mem & SDL_MASK[shift]) ); +} + +u64 SDR_MASK[8] = { 0x0000000000000000, 0x00000000000000ff, 0x000000000000ffff, 0x0000000000ffffff, + 0x00000000ffffffff, 0x000000ffffffffff, 0x0000ffffffffffff, 0x00ffffffffffffff }; +u32 SDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void SDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] << SDR_SHIFT[shift]) | + ( mem & SDR_MASK[shift]) ); +} + +void SQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + memWrite128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); +} + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +void MOVZ() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} +void MOVN() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] != 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +#include "Sifcmd.h" +/* +int __Deci2Call(int call, u32 *addr); +*/ +u32 *deci2addr = NULL; +u32 deci2handler; +char deci2buffer[256]; + +/* + * int Deci2Call(int, u_int *); + */ + +int __Deci2Call(int call, u32 *addr) { + if (call > 0x10) { + return -1; + } + + switch (call) { + case 1: // open + + deci2addr = (u32*)PSM(addr[1]); +#ifdef BIOS_LOG + BIOS_LOG("deci2open: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + deci2handler = addr[2]; + + return 1; + + case 2: // close + return 1; + + case 3: // reqsend + +#ifdef BIOS_LOG + BIOS_LOG("deci2reqsend: %x,%x,%x,%x: deci2addr: %x,%x,%x,buf=%x %x,%x,len=%x,%x\n", + addr[3], addr[2], addr[1], addr[0], + deci2addr[7], deci2addr[6], deci2addr[5], deci2addr[4], + deci2addr[3], deci2addr[2], deci2addr[1], deci2addr[0]); +#endif +// cpuRegs.pc = deci2handler; +// SysPrintf("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc)); + if (deci2addr == NULL) return 1; + if (deci2addr[1]>0xc){ + u8* pdeciaddr = dmaGetAddr(deci2addr[4]+0xc); + if( pdeciaddr == NULL ) pdeciaddr = PSM(deci2addr[4]+0xc); + else pdeciaddr += (deci2addr[4]+0xc)%16; + memcpy(deci2buffer, pdeciaddr, deci2addr[1]-0xc); + deci2buffer[deci2addr[1]-0xc>=255?255:deci2addr[1]-0xc]='\0'; + SysPrintf(deci2buffer); + } + deci2addr[3] = 0; + return 1; + + case 4: // poll +#ifdef BIOS_LOG + BIOS_LOG("deci2poll: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + return 1; + + case 5: // exrecv + return 1; + + case 6: // exsend + return 1; + + case 0x10://kputs + SysPrintf("%s", PSM(*addr)); + return 1; + } + + return 0; +} + + +void SYSCALL() { +#ifdef BIOS_LOG + u8 call; + + if (cpuRegs.GPR.n.v1.SL[0] < 0) + call = (u8)(-cpuRegs.GPR.n.v1.SL[0]); + else call = cpuRegs.GPR.n.v1.UC[0]; + BIOS_LOG("Bios call: %s (%x)\n", bios[call], call); + if (call == 0x7c && cpuRegs.GPR.n.a0.UL[0] == 0x10) { + SysPrintf("%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0]))); + } else + //if (call == 0x7c) SysPrintf("Deci2Call: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (call == 0x7c) __Deci2Call(cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0])); + if (call == 0x77) { + struct t_sif_dma_transfer *dmat; +// struct t_sif_cmd_header *hdr; +// struct t_sif_rpc_bind *bind; +// struct t_rpc_server_data *server; + int n_transfer; + u32 addr; +// int sid; + + n_transfer = cpuRegs.GPR.n.a1.UL[0] - 1; + if (n_transfer >= 0) { + addr = cpuRegs.GPR.n.a0.UL[0] + n_transfer * sizeof(struct t_sif_dma_transfer); + dmat = (struct t_sif_dma_transfer*)PSM(addr); + +#ifdef BIOS_LOG + BIOS_LOG("bios_%s: n_transfer=%d, size=%x, attr=%x, dest=%x, src=%x\n", + bios[cpuRegs.GPR.n.v1.UC[0]], n_transfer, + dmat->size, dmat->attr, + dmat->dest, dmat->src); +#endif + } +//Log=1; + } +#endif +// if (cpuRegs.GPR.n.v1.UD[0] == 0x77) Log=1; + cpuRegs.pc -= 4; + cpuException(0x20, cpuRegs.branch); +} + +void BREAK(void) { + cpuRegs.pc -= 4; + cpuException(0x24, cpuRegs.branch); +} + +void MFSA( void ) { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = (s64)cpuRegs.sa; +} + +void MTSA( void ) { + cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0]; +} + +void SYNC( void ) +{ +} + +void PREF( void ) +{ +} + + + +/********************************************************* +* Register trap * +* Format: OP rs, rt * +*********************************************************/ + +void TGE() { + if (cpuRegs.GPR.r[_Rs_].SD[0]>= cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEU() { + if (cpuRegs.GPR.r[_Rs_].UD[0]>= cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLT() { + if (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQ() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNE() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Trap with immediate operand * +* Format: OP rs, rt * +*********************************************************/ + +void TGEI() { + + if (cpuRegs.GPR.r[_Rs_].SD[0] >= _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] >= _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTI() { + if(cpuRegs.GPR.r[_Rs_].SD[0] < _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNEI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Sa intructions * +* Format: OP rs, rt * +*********************************************************/ + +void MTSAB() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3; +} + +void MTSAH() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4; +} + + + +/////////////////////////////////////////// + +int intInit() { + //detect cpu for use the optimaze asm code + return 0; +} + +void intReset() { + cpuRegs.branch = 0; + branch2 = 0; +} + +void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + + +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); +extern u32 vudump; + +void intExecuteVU0Block() { +int i; + +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) + break; + +#ifdef _DEBUG + prevbranch = VU0.branch; +#endif + vu0Exec(&VU0); +#ifdef _DEBUG + if( (vudump&8) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + } + + if( i < 0 && (VU0.branch || VU0.ebit) ) { + // execute one more + vu0Exec(&VU0); + } +} + +void intExecuteVU1Block() { + + int i; +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) + break; + +#ifdef _DEBUG + prevbranch = VU1.branch; +#endif + vu1Exec(&VU1); +#ifdef _DEBUG + if( (vudump&8) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU1.VI[ REG_TPC ].UL); + iDumpVU1Registers(); + } +#endif + } + + if( i < 0 && (VU1.branch || VU1.ebit) ) { + // execute one more + vu1Exec(&VU1); + } +} + + +void intEnableVU0micro(int enable) { +} + +void intEnableVU1micro(int enable) { +} + +void intStep() { + execI(); +} + +void intClear(u32 Addr, u32 Size) { +} + +void intVU0Clear(u32 Addr, u32 Size) { +} + +void intVU1Clear(u32 Addr, u32 Size) { +} + +void intShutdown() { +} + +R5900cpu intCpu = { + intInit, + intReset, + intStep, + intExecute, + intExecuteBlock, + intExecuteVU0Block, + intExecuteVU1Block, + intEnableVU0micro, + intEnableVU1micro, + intClear, + intVU0Clear, + intVU1Clear, + intShutdown +}; + diff --git a/Linux/.pixmaps/pcsxAbout.xpm b/Linux/.pixmaps/pcsxAbout.xpm new file mode 100644 index 0000000000..2ebc445d15 --- /dev/null +++ b/Linux/.pixmaps/pcsxAbout.xpm @@ -0,0 +1,334 @@ +/* XPM */ +static char *pcsxAbout[] = { +/* columns rows colors chars-per-pixel */ +"314 176 152 2", +" c #252d42", +". c #282e45", +"X c #282f48", +"o c #273046", +"O c #283046", +"+ c #2a334b", +"@ c #2d3650", +"# c #2e3853", +"$ c #303651", +"% c #303955", +"& c #333d5b", +"* c #383f57", +"= c #383e5d", +"- c #35405e", +"; c #39415d", +": c #364161", +"> c #384465", +", c #3a4668", +"< c #3e4866", +"1 c #3c496c", +"2 c #3e4b70", +"3 c #40475b", +"4 c #41485d", +"5 c #404767", +"6 c #424a63", +"7 c #434c6c", +"8 c #484f61", +"9 c #464e70", +"0 c #44506f", +"q c #4c5263", +"w c #465071", +"e c #495273", +"r c #4d5679", +"t c #4e5974", +"y c #4e587b", +"u c #515665", +"i c #535866", +"p c #545968", +"a c #595d69", +"s c #50577b", +"d c #505a75", +"f c #51597d", +"g c #5c606a", +"h c #55617f", +"j c #5a637b", +"k c #64666d", +"l c #65686e", +"z c #666870", +"x c #6b6d71", +"c c #6e7073", +"v c #767676", +"b c #545d81", +"n c #566085", +"m c #586185", +"M c #5b648a", +"N c #5e6883", +"B c #5e688d", +"V c #666d84", +"C c #606a8b", +"Z c #686f86", +"A c #626b93", +"S c #656f98", +"D c #687085", +"F c #6a738c", +"G c #667097", +"H c #667098", +"J c #6d7691", +"K c #6b749d", +"L c #6e7893", +"P c #72788c", +"I c #757d93", +"U c #6d76a0", +"Y c #6e78a1", +"T c #717ba4", +"R c #747ea8", +"E c #7c8397", +"W c #79829a", +"Q c #7680ab", +"! c #7a84ae", +"~ c #7c85b1", +"^ c #7e88b3", +"/ c #808080", +"( c #80838f", +") c #888888", +"_ c #808799", +"` c #82899d", +"' c gray57", +"] c gray60", +"[ c #858da3", +"{ c #858eba", +"} c #8d93a5", +"| c #8f95a8", +" . c #8690bc", +".. c #8891bd", +"X. c #9096a9", +"o. c #999ead", +"O. c #9aa0af", +"+. c #9ca2b4", +"@. c #a2a2a2", +"#. c #aaaaaa", +"$. c #a5a9b6", +"%. c #a7acba", +"&. c #a8adbc", +"*. c #aab0bf", +"=. c #bababa", +"-. c #8e96c3", +";. c #8e98c4", +":. c #9099c6", +">. c #959dca", +",. c #96a0cc", +"<. c #98a0cd", +"1. c #9ca5d1", +"2. c #a4add9", +"3. c #aab0c0", +"4. c #b3b6c2", +"5. c #b4b8c4", +"6. c #b6bbc8", +"7. c #adb5e1", +"8. c #b0b7e3", +"9. c #b0b8e3", +"0. c #bec2cb", +"q. c #bfc7ef", +"w. c #bfc7f0", +"e. c #c2c2c2", +"r. c #c0c3cd", +"t. c gray80", +"y. c #c2c6d1", +"u. c #ccced6", +"i. c #cdd0d7", +"p. c #ced1d9", +"a. c #d0d2d7", +"s. c #d4d5d9", +"d. c #dddddd", +"f. c #c0c7f0", +"g. c #c3cbf2", +"h. c #c8cef4", +"j. c #cad0f5", +"k. c #d9dbe1", +"l. c #d2d8f6", +"z. c #dbdff8", +"x. c #dce0f8", +"c. c gray90", +"v. c #e5e7eb", +"b. c #e6e8ec", +"n. c #eeeeee", +"m. c #e1e5f9", +"M. c #ebeefb", +"N. c #eff1fc", +"B. c #f2f3f5", +"V. c #f0f1fc", +"C. c #f7f8fd", +"Z. c #fefefe", +/* pixels */ +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 2 , , , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , > , > > , > , , : , , : , : , : , : > > > > : > > , : : : : > : : > : : : : : : : - : : - : - - : - - - - - - & - - & - - & & & & & & : & & & & & & & & & & & & & # # # # # & & # & # & # # & # # # # # # & # # & # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ X @ @ + @ @ + @ + @ + @ + + @ + + @ + + @ + + + + + + + + + + + + + + o + + o + + + o + X o X X + o o O O O O O X X O . . . . . . . . . o o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 2 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , , , 2 1 , 1 , , , , , 1 , , , , , , , , , , , , > , , , > , > : , , : : , , : , : , : > > , : : > > : : : , : : : : > : : : : : : : : : - : - - - : - - - - - - & - - & - - & : & : & : & & & & & & & & & # & & # & & & & & : & # # & # & # & & # # & & # & # # # # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + + @ + + + + + + + + + + + + + + + o X + + o o + o + o + X X + + + o X o X X O O O O o o O X O . . . o o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 , 2 , 1 1 1 , 1 1 1 1 , , 1 , 1 1 , 1 1 , 1 , 1 , , , , , , , , , , , > , , > , , > , , , : , : : , : , > : , > > : : > > : > : : > : : : : : > - : : - : - - : : : - : - - - - - & - & & - & - & & & & & & & & & & & & & & & & & # & # : # # # & & & & & # & # # & & # & # # # # # # # # & # # % # @ # # @ # # @ % @ @ @ @ @ @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + @ + + + + + + + + + + + + + + + + o + + + + X + o + + o + o o @ + X + X o o o X + X O O O O X X . . . o o . . o . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 2 , 2 2 1 1 1 1 , , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , , > , , > , > , > , > : , , > , , , : , : > > : > > > : > : > : : > : : : : : : : : - : : - : : - - - - - - - - - - - - - - - - & : & & : & & & & & & & & & # & & & & & & & # & : # & # # & # # & # # & # # # & & & # # & # # # # # # # # # # @ # @ @ # @ % @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ + + @ + + @ + + + @ + + + + + + + X + + + + + X + o + + o + o o X X X o o + o X O O O O X O O O O . . . o . o . . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 2 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , > , : , : : : , : , > : , , : , : > > , : > : : , : , : : : : > : : : : : : : : - - - - - - - - - : & & - - - & & & : & & & & & & & & & & & & & & & & : # # & & # # & # & # & # & & # # & # # # # & # # & # # # # @ # % % # # # # @ # @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ @ + @ @ + @ + + @ + + @ + + + + + + + + + + + + + + + + + + o o @ X o + o + o + o + + X X O O + O O O . . O . . . o o o o o . o o . . . . ", +"9 2 2 2 w 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 , 1 , 1 , 1 , , , 1 1 1 , 1 , , , , , , , , , , , , > , > > , , , > , , , : , : , , : : , : > > : : : , : : : : : : > : : : : : : - : : : - : : - - - - - - - & - : - & - & - & & & & & & & & & & & & & & & # & : # # # : # & & # & # & # & # # & # & # & # & # # # # # # # # % # @ # # # @ # # @ # @ @ @ @ @ # @ @ @ @ X @ @ @ + + @ @ @ + + + + + @ + @ + + + @ + + + + + + + X + X + o + o X + + o o + o o o + o o o o o o O O O O O O O . . O . o . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , , 1 1 , 1 , 1 , 1 , , 1 , , , , , , , , , : , > , , , , > , > > , , , : , , : , : : > , : , : > > : , : : : > : : : : : : : : : : : : - : - : : : - - : - - - : & & - & - - - & : & & : & & & & & & & & & & & # & : & & : # : & & # & # & # & # & # # # # # # # # # # # # # # # # # # # @ @ # @ @ # @ # @ @ @ # @ @ @ @ @ X @ @ @ + + + @ + @ @ + @ + + + + + + @ + + + + + + + + + o + o + X + o + + + X o + + o o + o o + o O O O O O O . . O . o . . o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , , , , > , > , > , , > : , , > > , , : , > > > : > : > : : > : > : : > : : : : : : : : - : : - : - - - - - - - - - & : - - & - & & & : & & & & & : & & & & & & & & & & # # & # # & # & & # & # # & & # & # & # & # # & & # # # # & # # # # # # # # @ # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + X + o + o @ + o o + o o + o X + O O O O O O O O o o . . o o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 2 , , , , , 1 , , 1 , , , , , , , , , , , , , , > , , > , , , , , , : , , : , , : > > , > > > > , : : , : : , : > : : : : : : > : : : - : - - : - - - - - - - - - : & & & & : & & : & & & & & & & & & & & & & # & # & # & # & & & # & # & # & # & # # & & # % # # & # # % @ & & @ & @ @ @ # @ @ # # @ @ @ @ @ @ @ @ # @ @ @ @ @ + @ + + @ @ + @ + @ @ + + @ + @ + + + + + + + + + + + o + + o + o + + + O + + O + + + X X o o o O O O O O X X O O O O O O . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 2 2 , 2 , , , , , , 1 , , , , , , , , , , , , , , , > , : , : , : , : , , : , > > : > : : > : : , : , : : : : > : : : : : : : : : : - : - : - - : - - - - - : & & : : & & : & & : & & & & & & & & & & & & & & & & & & & & # & # # & # & # & # & # # # % % # # # # # % @ @ @ @ @ % @ # # @ # @ # @ # # @ # @ X @ # X X # @ @ @ @ @ @ @ + + + @ + + + + + + + + + + + + + + + o + + + + o + + X + O O + + o O o X X X + o O X X X O O O O X . o O O O X o O . . o o o o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 1 1 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 , , 2 , 2 , 1 1 1 , 2 , , 1 , , , , , , , , , , , , , > , : : , , , : , , : : , > > : , : : : , , : : : , : > : , : , : : : : : - : : - : - : - - - - - - - & & : & : & & & & & & & : & & & & & & & & & & & & # & # & & & # & & # # & # # & & # # & # & # & # # # & & @ @ @ % @ @ % # @ @ @ # @ # @ @ @ # @ # X # # @ @ X @ @ @ @ @ + @ + @ + + @ + @ + + + + + + + + + + + + + + + X + X + + + o + o X o + X X X + o + + o O + O O O O O O X o o O O o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 2 , 1 , , , , , , , , , , , 1 , , , , , , , , , > , , > , , , , : , , , : , , > , : , : , , : : : : , : : : : : : : : : : : : : : - : : - : - : - - - - - - : : : & & : & : & : & & & & & & # & & & & & & & & & & & & # & & # & & & # & & # # & & # # # # # & # # # @ @ & @ @ % # @ # # # @ @ # @ @ @ @ @ @ # # # @ @ @ @ @ + @ + + @ + + @ + @ + @ + + + @ + + + @ + + + + + + + + + + + + O + + + O + + X + o X X O O o o O O O O O O X X O X O O O o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 , , 1 , 2 1 , , , , , 1 , , , , , > , , , , , , > , : , , , , : , , : : , > > , : , : : > , : , : : : : : : : , : : : : : : : : : : : : - - - - - - - - & : & : & - & & & : & : & & & & & & & & & & & & & & & & # # & # & # & # & & & & # # # & # % & # & # # # # & # # & & @ % @ @ % @ @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + X + + + o + + X + + O + X + X + + O + O O O O O O O O O O O O . X O O o . o O . . o . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 2 1 , 1 , 1 1 , , , 1 1 , , , , , , , , , , , , , > , , , , , : , : , : , , , : > > : , : , > > : > > : , : , : : : : : : : : : : : : : : : - : : - : - - - - - & : & & & : : & & & & & & & & : & & & & & & # & # & & & & & # & & & & # # # # & & # & # # # # # # # # # # # @ @ % @ @ @ @ @ & @ @ # # @ @ @ @ @ @ @ @ @ X @ X @ @ + + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + + + + + O + + o X + + o O O O O O + O O O O O O O o O . O O . . O . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , : , : , , : , , : , , : , , > > , : > , : : : > > : , : , : : : : : : : : : : : : : : : - - : : - - - - - - : : & : : : & & : & & & : & & & # & & & & & & # & & & & & # & # & # # & & # & # & # # & # & # # & # # # # # # & @ @ @ % # # # # # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ + + @ + + @ + + @ @ + + + + + + + + + + + o + + + o + + o o + + o O + + O + X O + O O O O O O O O O X O o O O O X o . . . . . o . . . o ", +"e 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , , , , 1 , , 1 , , , , , , , , > , , , , , , , : , , , : , : , > > : > , : : , , : > > : : : : : , > : : : : : : : : : : : : : - - - - - - - - : & & - & & : & & & : & & & & & & & & & & & & & & & & # & & & & & # & & # & # & # & # # # & % & # # & # # # # # @ & % @ # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ + + @ + + + @ + + @ + + + + + + + + + + o + + X + + + + X X + X X + O O O + + O O O O O O O . X O . . . . . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , 1 , 1 1 1 1 , , 1 > , 1 > , , 1 , , , , , , , , , , , , , , , , : : , , : > > > > > , > > > : : , : > : : > : > : > : : : : : : : - : - - - - - - - - - & - - : & & & & : - & & : & & & & : & & & & & & # & & & # & & & # & # & # & # & # & & # # # & # % % % % % % % % @ # # # # # @ @ @ # # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X X @ + + @ + + @ + + + + + + + + + + + O + + + o + o + + O + O O O + O + X O O + O + X O X o O . . . . o o . . . . o . O O O O ", +"2 2 2 2 2 2 2 e 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 1 1 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 1 1 1 , , 1 1 , , 1 , , , , , , , , , : , , , , : , , : , , , , : , > > > > : : > : , : > : : : , : : > : : : : : : : : - : : : - : : : - : - - - - - - & : : : & & - - & & : & & & & & & & & & & & & & & & & # & & & # % & # & # & # # # & # & # # % % % @ % @ % % @ % @ # # @ % # @ @ # @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X @ X @ X @ @ + @ + + + + + + + + + + + + + + + + + O X + + o + X o O O O + O O O O O O X X O O O O O O . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 1 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , , , 1 , , , 1 , , , , , , , , , , : , : : , : , : , , : , : > > > > > > > > > > : > : : : : : : : : : > : : : : : : - : : - - - : - - - - - & : & & & : : & & - - & & & & - & & # : & & & & & & & & & # # & & & & # & # & # # & & # % # # # @ % % % @ % % @ % # # # @ % # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ + @ + + + + + + + + + + + + O + + + + O + O O + + O + o + O + O + O o O + O O O O O O O X . . . o . . O O . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , , 2 , , 1 , , 1 , 1 , , > 1 , , , , , , , , , , , , , , , , , , > , : , , , : > > > > > > > : : : , : > , : > > : > : : : : : : : : : : : - : : - - - - : - - - - : & : & & & - & & & & & & & & & & & # : # & # & & & & & & # # & % & & # # & % # & # # & % & % % % @ % % % # # # # # @ # @ # # @ @ # @ # @ @ @ @ @ @ @ @ X @ @ @ X @ @ @ X @ + @ + + + + + @ @ + + + X + + + + + + + O + + + + + o + + o + X + O O O O O X O O O O O X X . . . . o . X O o . . o O . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , , 2 , 1 , 1 , , 1 , 1 , 1 , , , , , , , , , > , , , : , : , , : , > , : , > , , , > > > > > > > > : > > : : > : > : > : : : : : : > - : > - : : - - : - - - - - - - & - & & & : & & & & - & & & & & & & & & # & & & & & # & & & # # & & & & # # # % % & % # % # # % # @ % % # # % % @ % @ # # # $ # @ # @ @ @ @ @ @ @ @ @ @ # @ @ + @ @ @ X @ X @ @ + @ @ + + + + + + + + + + + + + + X + + + O O + O O + O O + o O + O + O O O O + X O O O O O . o . . . . o . O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , 1 , , , , , , , , , , , , , , > , , , , > , > > > , : > > > > : > > > > > : > > : : : : > : > : : > : - - : - : - - : : - - - - - - - - - - : : & & : & - - & - & - & & & & & & : & & & # & & # & & & & # # # # & & & & % % % % % % # % % @ % % # % @ # # @ % # # @ # @ # @ @ # @ @ @ @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + + @ @ + + + + + + + + + + + + + + + + + + + + + + O + o + + O O O O + O O O O X O o O O . o O . o . . o O O O O O . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , , , , : , , , , : , > > > > > > > > > > : > > > > : > : , : : : : > : : : : - > > - - - : - - : : - - - - - & : & : : & & : : & & & & & & & & & & & # & & # & & & & & & # & & & & # & # & # % % % % # # % & # % % % # # # # @ % # # # # # @ @ # # @ # @ @ @ @ @ # X @ @ @ @ @ @ @ X + @ X @ + @ @ + + + + + + + + + + + + + o + O + + O + O O + O O + + o o O + O O O + + O O O O O O X O . o . o o . . . . O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 2 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , : , , , : , : , : , , > > > > > > > > > > : : > > > : > : : > : : : : > : : > - - - - : - : : - - : - - - - : & : & & & : & & & - & & & : & & & & & & & & & & # & & # & # & & # & # & & # & % % % % & # % # % # % % % % # # % @ % @ $ # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ X @ + @ @ X @ + @ + + @ + @ + + + @ + + + + + + + + + + O + + + O + O + o X + O X + O O O O O O O O O O O . O o o . o o . . O O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , , 1 1 , 1 > 1 1 > 1 , , , , > , , , , , : , , : , , , , , > , > > > : , > > > > > > > > : > : , : , > : : : > : : : - : : : - : - : - : : - - - - - & : & : & & : & & & & & & : & & & & & : & & & : & & : & & & & # # & & # & # & # # & % % % % % % % # # # % % # # # % # @ % @ @ % @ # @ # @ # @ # @ @ @ @ # @ @ @ @ @ @ + + @ + + + @ + + + + + + @ + + @ + + + + X + + X + + O + + X X X + O + O O + + o o O O O O O O O O O X . . . o . . o . o . . . o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 1 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 1 > 1 > , , 1 , , , , , , , , , , , , , , > : , > > > > > , : , > : : > : > : > : : : : : > : : : : : : > : : : : : : - : - : - - - - - : & : & & : & & & : : & & & & & & & & # & & & & # & # # # & # & & # # & # & # & & % % % % % # % % % % # # # % # # @ @ % # # # # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + + @ @ + + @ @ + @ + + @ @ + + + + + + + + + + + + + X + + + + + + + X + O X O X X + O O O + O X O O O O O O . . o . o . O o O . o O O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 > 1 1 > , 1 , , , , , > , , , , , , > , : , > , > , > , , : , : > > : > > : > : , : , : : : > : : : : : : - : : : - - - - - - - - - - - : : & : : & : & & & & - & : & & & & & & & & : # & & & & # & & & & & & & & # & # # % % % % % % % # # # % % # # # # % @ # @ # # @ # # # @ @ # @ @ @ @ @ @ # # @ @ @ @ @ + + @ @ X + @ + + @ X + + + + + + + + + + + + + O + + + X X + X X O + O + O O X X O O O O X O O O O X o O . . o . . o . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , 1 1 , 1 1 > 1 , , , , , , , , : , , , : , : , , , > > > > > > > > > > > > > > > > : , : : : : , : : : > : : : : : : : - : : : : - - : - - - - & & : & & & : & : & & & & & & & & & & : # # # # & & # & & & # & # & # # # & # & # & % % % % % % % % # % % % % # # # % # # # @ # @ # @ @ @ @ @ @ @ # X @ # X @ @ X + @ @ @ + @ @ @ + @ + + + @ + + + + + + + + + + + + + + + X + O O + + O X X + + O + X O O + O X + O O O O o O . O . . . . o . o . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , 1 , , , 1 > , , , , , , > , , , , , , , , , , , > : > > > > : , > , : : > , : > > : : : , : : : : : : : : : : : : : - - : - : - - - - - - - : : & : : & - & & & - & : & & & & & & & & & & & & : & & & & # & & # & & & # % % % % % % % % % % % % % % # # # % % # % # % # # # # # @ # @ @ @ @ @ @ @ @ @ @ X # @ @ @ + @ + @ + + + @ + + + + @ + + + + + + + + + + O + + + O + + + + O + O + O O O O O + O + X O X O O O O O O O o o o o o . . . . . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , , , , , , , , , 1 , , , , , , , , , , , : , : : , , , , , > , > > , > : : , , : : , : > : : , : : : : , : : : : : : : : : : : - - - : - - - - - - & & : & & - : & : & & & & & & & & & & & & # & & & # # # & # & & % % & # % & % % % & % % % % % % # % # # # # # # # # # @ @ @ % @ # @ @ @ @ # @ @ @ @ @ X @ @ @ @ @ @ @ @ + @ @ X + @ + @ @ + + + + + + + + + + + + + + + O O + + + O O + O + O + + + O X O O O X O O O O O O O . O o o o . . . o . . . o o o o O ", +"2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , , , 1 , 1 , , , , , , , , , , , , , , , > , , , > , : , , , > > , > : , , > > > , : : : > > : : : : : : : : : : : : : : : : - : : : - - - - - - - - : & : & : & & & & & & & & & & & & & & & & & & & & # & & & & # & % & % & % & % & % % % % % % % % % # % # # % # # % @ # # @ # @ @ @ # # # @ @ @ @ @ @ @ @ @ @ @ # + + @ + @ @ + @ @ @ + + + @ + + + + + + + + + + + + + + + + + O + O + O O X + O O O O + O O O O O O O O O O O o O . . . o . . o o o . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , > , , > , , , > : , , > > , > > > > : > > > : > : , > : , : , : , : : : : : : , : : : - : - - : : - - : - - - - & : & : & - & : : & & : & & & & & & & & & & & & : # & & # : # # & % & # & # % % % & % % % % % % % # # % # # # # $ # # # @ % % # @ @ @ @ @ @ @ @ @ @ @ @ X # @ X @ @ @ + @ + @ + + + @ + + + + @ + @ + + + + + + + + O O + + + O + + O + + + O O + O + O O + O O O O O O O O O O . . O . . . o . . . . o o O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , > , , , > > > > > , > , > > , : , : , : > : : > > > > > : : > : : > : : : : : : : : : : : : : & : & & : - - : - & : & : # : : : # : : & & & : & @ - - - # - - - @ - - @ # - # # - - # # - # # # # % % - # # % % # # # # # # # # # # % # # @ % # # @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + + @ + + + + @ + @ + + + + + + + + + + + + + X X + + + + X + o + O + O O O + X O X o O + O O O O O O . . . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , , 1 1 1 1 , , , , 1 , , 1 , , , , , , , , , , , , > 1 > 1 > 1 > > , > > , , : , > > : , , : : > : > : > : > > : : : : : : : : & : : : : : : : : : : - : & : : & : & : : : # # : : # # : : # - - # - @ - @ - - @ @ - - # - # # % # - # # % - - % % % # % # % % # & # # # # # # # # # # # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ + @ @ # + @ @ + @ # @ @ + @ + + @ + @ + + + + + + + + + + + + X + + + o X + + O O + O O o o + o o o O O O O + O X X . . . o . . o . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 2 2 1 1 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , > , , , 1 > > 1 > > > > , : : , > > , : , : , , > > > > > : : : : > > : > : : : : : : - & : : : : : - & : & : & : & & : : # : : : # : : & : & & # - - - - - # - - - - - # - - # # - - # # - # - # % % % % % % % & # # # % # & # % @ % % # # # # @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ + + + + + + + @ + + + + + + + + + + + o + + + + o X + o + O + X o + o + + + O O O O O O O X o X O . o o . O X O . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 1 1 1 1 1 2 2 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , 1 1 , , 1 1 , , 1 , , , , , , , , , > > > > > > > , > , , , : > , : > : , : : : > > > : > > : : : : : : : > : : : : : : : : : : & : : & : & : : & : & : : # & : : & & # : # & - - # # - # - # @ # - @ # - # - - # - # # - # % # % % % % % % % # # # & # # # # @ % @ % # @ @ # # @ @ @ # @ @ @ @ @ @ @ @ + @ + + # @ @ + @ + @ + @ + @ + @ + + + + + + + + + + + + + + o + + X + + X + + X + + O + o o O O + O O O O O X o O . . o . X . X . o o . o O O O O ", +"2 2 2 2 2 2 0 2 2 2 2 2 1 2 2 1 2 1 2 2 2 1 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 1 , , , , 1 , , 1 1 , , , , 1 , , , , , , > > 1 > > > > , , > , : > > , , : , > , : > , > > > : : > : > : : > : : : : : : : : : : & : & : : : & & : - - & : & & : & : & & : : # : # : # @ - - - - # - - - @ - # - # - # # % # - # # # % & % % % % % % % # % # # # % # % % # # # # # # @ # @ # @ # @ @ @ @ @ @ @ @ @ @ @ # + # + + @ + + # @ + + + + + + + + + + + + + + + + + + + + + o + X + + + o o X O O O X O O O O O + X O O . X X . . O o . . . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , 1 , , , , , , , , , > , , , , , , , > , 1 : > > > , > , : : , : , > > : : > : : > > : > : : > : : : : : : : : : = : : : : & : & : : : & : : & : & & : & & : : # : & : : : - - @ - - - # @ - - # - - # # # - % - # # - - % % % % % % % % % % % % # # # % # # # # # @ # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ + @ + # # + @ + @ + + + + @ + # @ + + + + + + + + + o + + o X + + + + X X + o + + X + + O + O O O O O O O X . O o O O . o o . O . o o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 1 , 1 1 1 , , , 1 , , 1 , , , , , , , , > > , > > > 1 > , , : , , , > > , : : , : > , > > > > : : > : > : : > : > : : : : : : : : : : & & : : : - & - : & : & : : : & : # : & & & & # : - - @ - # - - - # - # @ # - # - # - # # # # - % % % % % % % % % # # # % % # # # # @ % @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ @ + @ + @ + + @ + + + + + + + + + + + + + + + + + X + + + + + X X X X + o X + O + + O + O O O O O O O O . O O o o . O . X o o . . o . . O O O O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , , , , 1 , , 1 , 1 , , , , , , , , , , , > , , , , , 1 > > > , : , > > : , > , : > > > > : : : : > > > : > : > > : : : : : : : : : : : : : : : : : & : & : & : & & : & & & & # : : # : & & & # - - - - # # - - # - - - # - # - # # - - # # # % & % % % % # % % % % % % # # # # # @ % # # % @ # @ # @ @ @ @ + @ @ @ @ @ @ + @ + @ @ @ @ + @ # + + + # + @ + @ + + + + + + + + + + + + + X o + + + X + X + + o + X O O O O + O O O O O O O O O . . . . O O . . . . . O O ", +"2 2 2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 1 1 2 1 2 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 1 , , , 1 1 , , , 1 , , , , , , > , > , , > > , , , : , : , : : , : , : > : > , > > > : > : : : : : : : : : : : : : : - : - : - : - - - - - & : : & : & : : : : : : & : # & # : # - - - # - - # - - # - - # - # # & & # # & # & % % & # # & # # # # # - # # % # + - - + - + + - # @ @ @ # @ # @ @ + # # @ + @ + @ + + @ @ + @ + + + # + @ + + + + + + + + + + + o + + o + o + + + O O + O + O X X O X O O O + X O O O O O O X . . . . . o . . . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 1 2 1 2 1 1 1 2 1 2 1 1 1 2 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , , 1 , , , , , 1 , , , , , , , , , , , , , > > 1 > : , , , , , , , : , , , > , > : > : : > > : > : : > : > : > : : : : : - - : - : - : - : - - : : & : & & & : # # : # : # : : : # - - # - - # - # @ # - # # - # # & # & & & # & # % & # & # % # % # # # # # # # # @ + + - O - + $ # # @ # @ @ @ @ # + @ + @ # @ @ + + # + @ + @ @ @ + + + @ + + + @ + + + + + + + + + + + + + + o + + + O + O + + + O + O X O X X O + O O O X O O . . . o o o . . . . . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 2 , 1 1 1 , , 1 1 1 1 , , 1 , 1 , , , 1 , , , , , , , , , , , > , , , > , > > , , : : , , : , : , : : > , : > : > : > > > : > > > : : > : : : : : : : : : : : - : - - : - & : & : & & : : # : : : : & : & : & & # - - # # # - - - # # - - # # - & # & # # & # & & & # # # & % % # # + - # # # # - + + + - O o + @ @ @ @ @ @ @ @ # # @ @ @ @ + @ # + @ @ @ + @ + + + @ + + @ + @ + + + + + + + + + + + + + + + o X + + X O + O O X + O + o o X X O O O O O X O O . . . o . . . . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 2 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , 1 , , , , , , , > , > , , , , > , , > , , : , , , : , , : , : , : > > : : : > : : > : : : : > : - : : : - : - : - : - - - - & : & : : & : : : # # : & & # : # : - - # - - - - # - - - - # - - # # & & # & # & # # % & # # % % # - # # # # # % # - @ - @ O - - + # @ # @ @ @ @ @ + @ @ # + # # @ + @ @ + + @ + @ # + + @ + + + + @ + + + + + + + + + o + + o + + + O X + O O + + O O O O X + X X O O O O + X O X O O o . . . o o o . o . o . o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 1 1 , 1 1 , 1 1 , , , 1 1 1 , 1 , , 1 1 , 1 , , , , , , , , , , > , > , , , > > > , : > , : , , : : , : , : : > : : , , : > > : : : : > : : : : : : : : : : - : - - - : - - - - - : & : & # : : : : # & : : : & # - # - - - @ @ - @ + - - # - # - & & & # # & # & # & # # % % % & - + # # - @ + - + - + @ + + - - # # # @ @ # @ @ # @ + + + @ @ @ @ @ + o @ @ @ @ + # + + + + + @ + + + + + + + + + + + + + + + o + + X O + O + O O O O O + + O + + + + O O + O O O O X X . . O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 2 2 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , , , 1 1 , , , , , , , , , , , , > , , , , , , , : , : , : , : : , : , > : : > > : : > > : : : : : : : : : : = : : - : : - - - - - - & & : : & : : # : : : & : & & : : - # - # - - - - - - - @ - # - # & # # & & # & # # # & & % # # # # + - + + + - @ @ @ + - - + + + @ # + # @ @ @ @ # + # @ # # + + + + # @ @ o + o + @ + + @ + + + + + + + + + + + + + o + o + + + O + X + O O O O + O + + + + + + + $ $ $ + $ + + + O O O O . . . . . . . o ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , , > , > , , > , > , , : : , , : , : , : , , : > : > : : : : > > : : : : : : : : : - : : : : : : - - : - - - - - - : & & : # : : # & # : # & & & & - - # - # - - # @ - - @ # - # - # & & # # & % & & # % % & % # % + - - + @ # + @ + - @ @ - + + - # @ # @ # @ @ @ + # + # @ + + @ @ + @ @ + @ @ + + + + + + + + + + @ + + + + + + + + o + + + o o + O O + O + O O + O + + @ + % % $ * # * * @ $ + + + O O O O o o o o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 2 1 1 1 1 1 1 1 1 1 2 1 , 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , 1 , , , , , , , , , > , , , , , , > , > > , : , , , > > , : , : , : : , : , : , , : : : : : : : > : : : : : : : : - : - : - - : : - - - : & & : : & : & : : : : # : & : # & # - - - @ - - # - - @ - - # - - & # & & & # & # # & % # # # # & - @ + - + - - O - @ + - + - + + @ # # # + @ @ @ @ @ # # + # # @ + # @ @ + + @ @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + O + + O + O + + + + + + % # * ; ; > : ; ; = * $ $ + + + O . . . . . o . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 2 2 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , 1 1 , 1 , , 1 1 , , , , , , , , , > , , , > , : , , , : , , : : , : , : , > : > : : , : > > : : : : : > : : : : : : : - : - : - - - - - - & - & : & : & & & : # : & & # : : & & & & & # & & & - 8 4 4 4 8 < 4 , , , < 4 4 4 8 4 4 4 4 4 4 4 4 4 4 4 4 8 4 4 - $ @ $ - + + - o # @ @ @ @ @ + @ + # @ + @ + # + @ @ + @ @ + @ + + + @ + + + @ + @ + + + + + + + + + + O + + + O + + X + + o + + + + + # = ; 5 7 2 e e e 1 7 < = # @ + + + O X . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 , 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , , , , , , , , , , , , , , > , > > , , : : , , : , , : , : , : > , : , > : : > : > : : : : : : : : : : - : : : : - : - - : - - : - : & : & & : & & & : & : & & & & & & & & & & & & 4 v v v v v v v v c v v v v v v v v v v v v v v v v v v v v v v k ; - + + - - $ # # @ # # @ # # @ @ @ @ @ @ + @ + @ @ + + @ @ + @ + @ + + @ + + + + + + O + + + + + + + O O + + O + X + o + O + + @ * * > 7 e s n M M m n f e 7 > * # + + O . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 > 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , , > , , , , , , : : , , : > , : > , : : , : > , : > : , : : : : : : : - : : : : : - : - : - - : - : & : : & : : & : & & & & : : & & & & & & & & & & # 4 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k $ @ O - $ @ # @ @ @ @ @ @ @ # @ # @ # # @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + + O + + X + o + o + + $ # * > w f M S U T R T K S m f 9 : * % + + O X . . . X . . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 , 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 , 1 , 1 , 1 1 , 1 , , 1 , , , , , , > > , , , : , , , : : , , , , : > > , : , : : , > : > : : : : : : : , : : : : : > - : - - - : - : - : - - : & : & & : & & & : & : & & & & & & & & & & & & & & & 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v x ; - + O # @ @ # @ @ @ # @ + @ + + + # + @ + @ @ + @ + @ + + @ + + @ + + + + + + + + O + + X + O + + + + + + + X + + + @ $ ; > 0 f C K ! ..;.;.;. .~ Y B f 7 : * $ + O . . . . . X X X X X X X X X . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 > 1 1 , , 1 > 1 > 1 , , , , , , , , , , , , , > > , , , : , , , : , > , > : , > > : > : : > : : > > : : : : , : : : - - : : : - : - - : - : & : & - : & : & & & : & & & & : & & & : & & & & & & # & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v l - # @ @ @ @ @ # @ @ @ @ @ + @ # + @ + @ @ + @ + @ + @ @ + + + + @ + @ + + + + + + + + + + O + + + O O X + + o X + + $ # ; 7 y A R { <.2.7.9.7.2.>.{ R A r 7 = $ $ + X O . O X + X X $ + + + X X X X ", +"2 2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , 1 1 1 1 > 1 1 , , , , 1 , 1 > , , , , , , , > > , , : , , , > : , : , : , , > , : , , : > : > : > , : : > : : : > : > : : : : > : : : - : - > - - : - : & : - : : & & : & : & & : : # & : # & & & & & & & & & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k # $ # @ # @ @ @ @ @ @ @ @ @ @ @ @ # + @ @ + @ + @ + @ + @ + + + + @ + + + @ + + + + + + + + O + + + O + + O + + + % = , e M K ..1.9.w.j.j.j.w.7.1.{ Y M w 5 * $ + + O O . + + + $ $ $ $ $ * $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 > 1 1 , , 1 , , , 1 , , 1 , , , , , , , , , , > , , , , > : , , , , : > : > > : , , : : , , , : : , : : > , : : : : : : : - : : - : : : - : : - - : - - - & : & : : - & & & & & : : & & & # & & & & & & # 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 $ # @ @ @ # # # @ @ @ @ @ @ + @ + + # @ @ + @ @ + + + + + @ + @ + + + + + + + + + + + + + + + O + + + O + + + + # ; 7 f S ~ <.9.g.l.x.x.x.l.h.9.>.! G r 6 & $ + + O O + + + % * * = = 3 * * = $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , , 1 , 1 , 1 > , 1 > , , , , , , , , , , , , > > > , , , : , > > , , > > > : : , : > : : : , : : > : > : : : > : : : : : : : : : - - - - : - & : : & : & : & & & : & & : & & : # : # : & & & & & & & 0 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v c # # @ # # @ + @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + @ + @ @ + + + + + + @ + + + + + + + + O + O + + O + o + o + + @ % : 7 n U ..2.w.l.m.M.N.M.m.l.w.2.{ Y b 9 = $ + + + + + $ % = > 6 7 9 9 9 7 5 5 = ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , 1 , , , , , 1 , , , , , > , > > , , , , , > , > , : , , : , : , : , : : > > : , : : > : : : : : : : : : : : - : - - - : : : & : & & & & : & & : - & : & # : : # : & : & & & & & & & & , D c v c v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 # @ @ # # @ # @ @ @ @ + @ @ @ + @ + @ @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + O + + + + + * > e m T :.8.h.z.M.C.C.C.M.z.j.7.;.T M w ; $ $ X + $ $ * ; 7 w r b m M m b s 9 5 = % $ X $ . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > > > , , > > > , : : , : , : , : : , : > , : : : : > : > : > : : : : : - : - : > - & & : : : : : : & : & : : # - & & - & & : : # : & & & & & & & # : h l l l l l l l l l l l l l l l l l l l l l l v v v v v v v v v v v v v v v c @ # @ @ @ @ # + @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + @ + + + + @ + + + + + + # + @ @ + $ + + + + O + X + X + + $ & ; e C R :.9.h.m.V.Z.Z.Z.V.x.j.7.:.T M e 5 $ $ + + $ * : 7 r b S K T T T K A m s 7 3 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 2 1 2 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 , , , , 1 , , , , 1 , 1 , , , , 1 , , , , , , , > , > > , > , , > , , > , > , , : , : , : > , : > : : > : > : > : > : : : : > : : > - : - > - : : & : & : : & : & : & - - : & : & & & & # & : & & & & & & & & & & - & & # & # - # - - # & - % # - # # # & % % # g v v v v v v v v v v v v v v - - # @ @ @ @ @ @ @ @ @ @ @ + @ @ + + @ + @ + + @ X + @ + + + + @ + + + @ % # # # @ % $ % + + + + X + X + + + & > e M R ;.7.h.m.M.C.C.C.M.x.h.7.;.T M w ; * $ + $ * ; 7 s A T R ..-.-.-.{ ! K B s 7 3 $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , , , , , , , , , , , , , > > , > , > , > > , > > , > , : > , : , : , > : , : > : > > : : : : : : : : : : : - - : - : - - & : : : & : : & & - - - - & & - & & & : : : # # & & & & & # & & & & & & & & # & # - # # - # # # # # # & % % # # # @ g v v v v v v v v v v v v v i o @ @ # @ # @ @ + @ @ @ @ + @ + @ @ + @ + @ + @ @ + @ + @ + @ + @ @ # % # % % = # * * * @ # % $ + + + + + @ * ; w b K { 2.q.l.m.M.V.M.m.l.w.2.{ K b 7 ; $ $ $ $ = 6 r C R { >.2.2.8.7.2.>.{ Y C s 4 * * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , > , , > , , , : , : > , : : , : : > : : , : : > : : : > > : : > : : : : : - : : : > - - > : : & : : : & : : - : & : # - & & : # : & : : & & & & & & & & & # & # & & # & # - # # - # # % % & # # # & # & # # # - v v v v v v v v v v v v v c @ @ @ + # # @ # + + # @ @ @ @ @ + @ @ @ + @ + + X @ + + @ X + + @ $ % & = = : < < > : ; = # @ $ + + + + + $ # = 7 b S ~ <.9.h.l.z.x.x.l.h.9.>.~ G s 7 * % $ $ % 3 e m K { 1.8.f.h.j.h.f.8.1.{ U b r ; * . . . ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , , 1 1 1 , , , , , , , , , , , > , , , : , , > : > , > , > , > , : , > > > , : : , > > > > : : : > : : > : : : : : - : - - - - - : & : & : : & : & & : : : & & & & : & # & : # & & & & & & # & & & & & & & & # # - - # # - # - & % & % & # % # # # # p v v v v v v v v v v v v v - @ @ @ # + # + # # # @ + @ + @ + + @ @ @ + + + @ + @ + + @ @ @ # * = : 5 7 e e e e e 7 5 > = $ $ $ + + + + $ & , e b Y { 1.9.w.g.j.j.w.9.1.{ K M e : % % $ % = 7 s G R <.8.h.l.z.m.z.l.h.8.>.R A s 5 * + . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 1 2 1 1 2 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , , 1 , 1 1 , , , , 1 1 , , , , , , , > , , > , > > , > , , , , > > > > > , , > , > : > > > : : > > : : : > : : : > : : : : : - > - > - - : - : - & : : & & : & : & # : : : & : & : # : & & & & & & & & & # & & & & & & & # - # # # # - % # & # % # # & % - # # ; v v v v v v v v v v v v v < @ @ @ @ @ # # # # + + @ @ + @ @ + @ + @ + @ + + + @ + @ + $ % % : 5 7 r b b M M M m f r 7 < = # $ + + + + $ % = 7 y A T { >.2.7.7.7.2.>.{ T A r 7 = * + % % = 7 b K .2.f.l.m.M.M.M.m.l.g.2...K b 7 . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 1 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , , , , , > , > , > > , > > : : , : > , : , : , : : > > : : > : > : : : : : : : : - - - : - - & : : : : & : : & : # - : - & & & # : : & # : & & & & & & & & & & & # # & # & - # # - - # # # % # & # # % # # # # # # l v v v v v v v v v v v v q - @ @ @ @ @ @ @ + @ # @ @ @ + @ @ @ + + @ + @ @ + + @ + $ % & : 5 w f M K K R Q R K S M b 9 5 = & $ + + + $ $ = > 7 b A Y ~ -.;.:.-.-.~ Y C f 9 > * $ + $ % : w b Y ;.8.h.z.M.C.C.C.M.z.j.2.-.T b 9 ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 2 , 2 , , 1 , 1 , , , 1 , 1 , , , , , , , , , , , , , , > > > , , > > > > > > : , > : , : > > > > : > > : > > : : : > > : : : : : : : : : : : & : : & : : - & - - & & & : & E u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.v.u.} 6 % & & # & & # # # & % % % % % # # % # % # * i v v v v v v v v v v v v a - o - O + + + - + + + + + @ @ + @ @ + @ # + + + @ + $ @ @ # = < e f G Y ^ ..:.>.;...^ K S b 9 < = @ + + + + $ % = : 9 s M S K T R T K A m s 7 : * $ $ + $ $ ; e C T :.8.h.m.N.C.Z.C.N.x.h.8.:.T N w ; $ + O . . ", +"2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 2 , , 1 , 1 , , 1 , , , , , , , 1 , , , , , > , > , > , > , > > , > , > , > , : > : : , , : > : > : > : : : : : : : : : : : : : : : : & : : : : & : : & : & = - - : & & : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.E % & & # # & & & # & % % % % % % % % # # # q v v v v v v v v v v v v k o - @ @ - + + O - + - O - + @ + @ + + + + + @ + + @ @ @ $ ; ; 0 f A R .<.2.7.9.7.2.<...R C f 7 : # $ $ + + + $ % * 3 7 e s m M M m m f w 7 > * % $ + + + * ; w b T ;.8.g.z.M.C.Z.C.M.z.h.7...T b 9 * $ + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , > , > , > > > > > > > > : > : > , : : , > > > > > > : > : : : > : : : : : : : : : - & : & : & : : & : : : & : & : & & +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.E # & # & & # & # % % % % % % % % % % $ # 3 v v v v v v v v v v v v k - o O @ + O - - O @ + + + + + # @ @ # + # @ + + + @ + # % ; < r M Y .1.9.w.j.j.j.q.9.1...K M e 7 = $ + + + + + $ % = : < 5 w w e w 7 5 5 ; * % + + + + + $ ; 7 b K { 2.f.l.m.M.N.N.m.l.f.2.{ K b 9 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , 1 , 1 1 , , , , , 1 , , , , , , , , , > , , , , , , > > 1 > > > , > , , > , > : : , : : > : : : : > : : > : : : : : : : : : : : : : - : : : & & : : & & : & : & : & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.m & & & # & # & & % % % % % % % % # # # 4 v v v v v v v v v v v v k o - - @ @ - O + + @ - o - + + # + + + @ + + @ # + + @ @ ; ; 0 f S ^ <.9.j.l.x.x.x.l.j.9.<.^ S s 7 = $ $ + + + + + $ @ # = = ; > ; ; ; = * % + + + + O + + $ * 7 r A { >.8.g.l.z.x.z.l.g.8.>.R S s 6 * $ O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 2 , 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 1 , , , 1 , 1 1 , , 1 , , , , , , , , > , , , , > , > 1 > , > > > > > , : , : , , : , > : > > > : > : > : : > : : : : : : : : : : - : : : & : : & & : : & : & : & & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.k.# & & % % % # % % % % % % % % % # # # 4 v v v v v v v v v v v v k + O $ - + + + + # + + - + + @ @ + + + + + + + @ + + @ # ; ; w n Y ..2.g.l.m.M.N.M.m.l.f.2. .K m w ; * + + + + O + + O $ $ % % $ * % * $ $ $ + + O O O O + $ % 5 r b K { 1.8.f.g.h.h.f.8.1.{ Y b w : $ $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 2 2 2 , 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , 1 1 1 1 1 , , 1 , , , , , , , , , , , , , > , , , > > , > , > > > , , > > > : , : , : : , : > > : > : > : > > : > : : : : : : : - : - : : - : & : : & : : & & : & : & = : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.L & # & % & & % % % % % % % % % % # % 4 v v v v v v v v v v v v k - O - + - + + - + # + + @ + + @ @ @ @ @ @ @ # + @ @ # # - > e M Q :.7.j.x.N.C.Z.C.M.x.h.8.:.Y B e > * % + + + X + + + + + + $ $ + $ + + + + + O X O O + + % = 5 s C U { >.2.8.8.8.2.>.{ T C s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , > > > > , > > > > > > , : , : , : : , > : > > : > : : : : : : : : : : : : : : : : : & : : : & : : : : & : & : : & & t D V V V N D V N V V V x V V V o.Z.Z.Z.Z.Z.Z.Z.Z.Z.0.# & & % % % % % % % % % % & % # % # 4 v v v v v v v v v v v v k - - o + + + @ @ + # # + + # + @ @ @ @ + @ + + @ + + # # - < r B Q :.9.j.x.N.C.Z.Z.B.m.j.9.>.Q B e > # @ + + X O + X X + + + + + + + O + O O O X X X O X O + $ % ; 7 f C K ! { ;.:.-.{ R Y C s 7 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 , 2 1 1 1 1 1 1 1 2 , 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 , , 1 , , , 1 1 , , , , , , > , , > , , , , , > , , > > , , > , > : , : , : , : : > > : : > : > : : > > : > : : : : : : : - : : : & : : : : & & : : & : & & : & & & - & & & - - - & & - & & & % # } Z.Z.Z.Z.Z.Z.Z.Z.Z.< # % & % & % % % % % % % # % % % % 8 v v v v v v v v v v v v k o O + - - o @ @ @ # + o - + @ @ + + + @ + @ + + @ @ # # - < e M Q ;.7.h.x.N.C.C.C.N.x.h.9.:.R M e > * + + + + O O O O X O + O O + O O O X O X O O O O O O + $ % 5 7 f b S K T T Y K S b s 7 > = $ + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 1 2 , 2 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , > , , > , > , , > > , > > > > > > , , > > > > > > > > : > : > : > > - > : : : : : - : : : - - - : : - - - : & : : & : & : & : & : & - & & & & & & & & & # & & & & = v.Z.Z.Z.Z.Z.Z.Z.Z.P # % % & # # # # # & # # # # % # # i v v v v v v v v v v v v k @ @ - + @ @ @ @ @ @ + @ @ + @ @ + @ @ + @ + + + + $ + % = < w n Y ..2.f.l.m.N.B.N.x.l.f.2...U b 9 : # @ + + O O O O O O O O O O O O O O o . O O X O O O O O X + $ * ; 6 e r b m M b b r e 7 3 * $ + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 , , 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , , , 1 , , , , , , , , , , , , > , > , > , > , > , > , : : > : > , : : : > > > : > : : > : : > : : : : : : : > - > : & - : - : & & & & : : & & & & & & - & - & & & & & & & & & & & & # } Z.Z.Z.Z.Z.Z.Z.Z.o.& & # & # & & & # # & & # % # # # l v v v v v v v v v v v v u # @ + o - @ @ @ @ @ @ @ o - + @ @ + @ + + + @ @ + @ + % % ; 9 b H ^ <.9.h.l.x.x.x.l.g.8.<.! S b 7 = % @ + X O + + O + O O O + O O O X X o o O O X O O X + + $ * ; : 6 9 w e e 7 6 : * $ $ + X . ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 : , & 1 : 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , , , > , , > , , , , > > > > , > > > > , > > > , : : > > > > > > : > : > : > : : : : : : : : - : - - - : : - : : : : : & & & : & : & : - & & - - & & - & & & & & & & % & j Z.Z.Z.Z.Z.Z.Z.Z.u.% & % % & # # & # # # # # % % # - v v v v v v v v v v v v v q - o + @ @ @ @ @ @ @ @ + + @ + @ @ + + @ + @ + @ + + % # % ; 1 r M Y .1.9.f.j.j.j.q.9.2...K M r < = # @ + + O O O O O X + O O O O O O O X X O O o O . . X X + $ $ $ ; ; ; = = * * * $ + + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 L J J L J W W W W W W B Q L L L C 7 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , , , C J F J J F F L F F J J F J , , , , , > , , , > 9 F F F F F F F F F C F F F 2 , : > > > : : F D F D D D F 7 : : : - - : : : Z F Z Z Z Z Z - & : & & : : : & : & - & & & - & & - & & & & & & & & & & # & Z.Z.Z.Z.Z.Z.Z.Z.u.# # & % # # & # & # & # & % # % u v v v v v v v v v v v v v ; @ @ o - @ @ @ @ @ + @ @ @ @ @ @ + @ @ + @ + + + + + + $ % = > 1 b A R ..<.2.9.9.9.2.<. .R A f 1 ; * % + O + + O + O O + O O O O O O O X o o O O O O X . . X . X + + + + $ $ $ $ * $ $ + + + X . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.m.C.C.Z.Z.Z.Z.Z.b.J 1 1 1 1 1 1 1 1 , , 1 , 1 1 I b.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.> , , , , > , > w &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F : , : > : > > 6.Z.Z.Z.Z.Z.Z.` : : : > : : : I Z.Z.Z.Z.Z.Z.u.& : & & : : & : & & & & & - & & & & & & & & & & & & & & % & & B.Z.Z.Z.Z.Z.Z.Z.B.# & & # % & # & # # % % # # # - c v v v v v v v v v v v v v + + - # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ + @ + + @ + @ % # ; < w b A K ^ ..;.>.;...^ Y A f e < = @ + + + + O + O + O O O O O + O O O . O O O . o . . . . . . + + + + + + $ + + + O . . + . . O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.N.V.Z.Z.Z.Z.Z.Z.Z.Z.I 1 1 1 1 1 1 1 1 1 1 1 , [ Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , > , , , , k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F > : > > > : > D Z.Z.Z.Z.Z.Z.r.: > : : : : > 6.Z.Z.Z.Z.Z.Z.I : : - : : & - & : & : & : & - - & & & - & & & & & & & & & % & u.Z.Z.Z.Z.Z.Z.Z.Z.& % % # & # & # % & % # # # @ a v v v v v v v v v v v v v k - - O @ @ - o @ @ @ @ + @ @ + + @ @ + + @ + @ + @ + + @ + @ % # ; 5 w b B S Y Y Q R Y S M s w < * % @ @ O O O + O O O + X + O O O O O O O o . O X O O o o . o . . . . . . O O O . + O O O O + + + + + + + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 , 1 , 1 1 1 H Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , , &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.F > , : > : : > > v.Z.Z.Z.Z.Z.Z.7 : : : : : 7 Z.Z.Z.Z.Z.Z.v.: : & & : & : - - & & : - & & & & & - & & & & & & & & & & & & & B.Z.Z.Z.Z.Z.Z.Z.B.# & % & # # # % # # # # # % i v v v v v v v v v v v v v v 4 - O + @ @ @ @ @ @ @ @ @ @ @ + + @ + @ @ + @ + @ + @ + + @ + # % = - > 7 r f m B B M n b e 7 > = % @ + + + O O O + O O O X O O O O O O O O O o . o o . . . . X . . . . . . X . . X . O + O X $ $ $ $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.3.1 1 1 1 1 1 1 1 , , p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , > y Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.C.F > : , : , : > : | Z.Z.Z.Z.Z.Z.` : : : : : ` Z.Z.Z.Z.Z.Z.o.: & : : & : : & - & : & : & - & - - & & & & & & & & # & & & # & Z.Z.Z.Z.Z.Z.Z.Z.s.i i i p p p i p i p p a k v v v v v v v v v v v v v v v c $ + + - # @ @ + @ @ @ @ + @ @ @ @ @ @ @ + @ + @ + @ + + @ + @ + % # = = > < 7 e e e e e 7 , > ; # $ @ + + O + + O X X + O + O O O O O O O O O O o X O . . O . . . o X . . O + + $ $ % * * 3 * 3 * * $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.k.L L L L L L +.Z.Z.Z.Z.Z.Z.B.1 1 1 1 , 2 , 1 1 C Z.Z.Z.Z.Z.Z.Z.+.J J J J P F F J J F , , , > , , &.Z.Z.Z.Z.Z.Z.k.W F F F F F F F F F 2 > > > : > : : : 0 B.Z.Z.Z.Z.Z.r.: : : : : k.Z.Z.Z.Z.Z.Z.7 : - : - - - : & : & - - - & - - - & = & & : & & & & # - # - & V Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v v v a - + @ @ - @ @ @ + @ @ o + # # @ @ @ @ + @ + @ + + @ + + @ + + @ $ $ % & = * : : < < > : ; * # % $ $ + + + O O O + X X O O X O X O + X O O X O O O O O . . o . X O o X X X X X $ % & 3 5 9 9 9 e 7 5 ; = % $ X X ", +"2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 1 2 +.Z.Z.Z.Z.Z.Z.W 1 1 1 1 1 1 1 1 &.Z.Z.Z.Z.Z.Z.+., , , , , , 1 , , , , , , , , , , b.Z.Z.Z.Z.Z.B.9 > > , > > > > > > > > > > : > > > > : > 5.Z.Z.Z.Z.Z.Z.7 : : : d Z.Z.Z.Z.Z.Z.4.- : - - - - - & : & : & - & & & & & & & & & & - & & & & & - # 8 0.Z.Z.Z.Z.Z.Z.Z.Z.e.v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ + O - O @ @ @ + - + - # + + @ @ + + + @ + @ @ + @ @ + @ @ @ + $ $ $ % % % = & & * * * # % % $ + + + O + O + X O + + O O + X X O O X X O X O O O O . O . o o O o X + + $ * = 5 9 s b b b b b s 9 7 = * $ O X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 2 e Z.Z.Z.Z.Z.Z.+.1 1 1 , 1 1 1 , p.Z.Z.Z.Z.Z.Z.w , 1 , , 1 , , , , , , , , , , , d Z.Z.Z.Z.Z.Z.&.> > > , > > > > > > > > > > > > : > > > : N Z.Z.Z.Z.Z.Z.` > - : %.Z.Z.Z.Z.Z.Z.C = - - - - - - & : & : - & - - & & : & : & & & & & & = & - & q / B.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v v u # - - O + - + @ @ @ + @ @ @ @ + # @ @ @ @ @ + o + @ + @ $ @ # # % # # $ # % # # * $ % # % $ $ $ + + + + X + X + O O O O O + X X + O O O O O O X O o X X o . . X X o O X O + $ * = 7 r b C S T T T K A b s 7 : * + X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 1 1 1 2 1 2 0.Z.Z.Z.Z.Z.p., 1 1 1 1 , , 1 Z.Z.Z.Z.Z.Z.0., 1 1 , , , , 1 , , , , , > , , , F Z.Z.Z.Z.Z.Z.F , > > > > , > > > > > > > : > > > - > > : : k.Z.Z.Z.Z.Z.u.- - - v.Z.Z.Z.Z.Z.k.- - - : - - - - : & : & - & & & & - & & & & & & & & & % & # 8 v t.Z.Z.Z.Z.Z.Z.Z.Z.Z.) v v v v v v v v v v v v v v v v v v v v v v v v v v l * @ + + - O + O - @ @ @ @ @ + # # + @ o @ @ + @ + @ @ + $ # # % = = = ; * = & & & # $ @ + $ + + + + X + O + + O O O + O + O o X o o O O O O X X O O O O . o . . O O X X + + * = 7 s C Y { { -.-.-.{ ! K C s 7 * % $ O ", +"2 2 2 2 9 2 2 2 2 2 2 1 2 2 1 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 2 1 1 2 1 2 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , > , +.Z.Z.Z.Z.Z.Z.9 , > , > > , > > > > : > > > > > : > : - > > W Z.Z.Z.Z.Z.Z.t > I Z.Z.Z.Z.Z.Z._ - : - - - - - - & : & : & & - - - 5 V V V V V V V V V V V V =.d.Z.Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v c ; # # + - - @ + + - + + + + + + + + + # + # + @ + @ @ @ # # # ; - > , < , 5 > : = = # % $ @ + + + + O O + X O O + + + + O O O O o O o O O O X O O X O O O O X o o . O . o O O + $ * 7 s C T { >.2.2.8.8.2.>.{ Y M s 7 * $ + ", +"2 2 2 2 2 2 2 2 2 2 9 2 2 1 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 7 1 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 , 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , > , , , , +.Z.Z.Z.Z.Z.Z., > > , > > > > > > > > > > : > > > > : > > > : B.Z.Z.Z.Z.Z.} - 6.Z.Z.Z.Z.Z.B.7 - - : - - - - - : & : & & : - e 4.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ # % + + O O - O - + - + - o + - + + + @ + + + @ # @ $ # = = > 7 1 9 e e e w 7 < : = # % @ + + + + O + + + + O O O O O + O + + O O O O O + X O o X X . X o o o . . O o o o O O O $ * : e m K { 1.8.f.h.j.h.f.8.1.{ K m 9 ; $ + ", +"2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 2 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , 1 , , 1 , , , , , , , , , +.Z.Z.Z.Z.Z.Z., , > > , , > > > > > > > > > > > : - > > - - > %.Z.Z.Z.Z.Z.k.1 Z.Z.Z.Z.Z.Z.5.- : - - - - - - - & : & : : - j B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.c.v v v v v v v v v v v v v v v v v v v v v v v v v k * % % $ # - + + - O - O + # @ - + - o - + @ @ + # # + + - # = : , 7 t b n M A M M b r 7 5 = % $ @ + + + + X + O O + O + O O + O O O O O O O O O O o O O O . o . . . . o . . X X X + $ * 5 r C ! >.8.h.l.z.z.z.l.g.9.>.~ C r 5 * + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 , 1 1 , Z.Z.Z.Z.Z.Z.+., , , , , , , , , , , , , , , , , +.Z.Z.Z.Z.Z.Z.F > > , > > > > > > > > > > > > > > > > > > > : t Z.Z.Z.Z.Z.Z.+.Z.Z.Z.Z.Z.Z.r : - : - - - - - - : & - & & e B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.' v v v v v v v v v v v v v v v v v v v v v v v k 8 $ % $ $ @ + @ @ + - + + + - @ + o o - + + + # + # + + + @ @ & ; 7 e b M H Y R R R K S M b w , = * $ + + + O + X O + + O O + O O + O O + O O O O O O . o o O o o . o o . o . . o O + + = 7 f K .2.f.l.m.M.V.M.m.l.q.2.{ K f 7 = $ ", +"2 e 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 W Z.Z.Z.Z.Z.Z.1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , 1 , , , , 1 , , , , , , , I Z.Z.Z.Z.Z.Z.%., > , > > > > > > > : > : > > > : > : : > > > : u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- : - - : - - - - - - = - - = u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v c a p p q t p i p p u i i i u u u p u 6 4 & # # # # # # # # @ O @ @ - + + + - - O + + + + + + # + + @ @ @ - ; < 0 n A Y ^ -.:.>.:...^ T C f e < = @ + + + + + O + X + O + O O + + X O O O O O O O O O O O O . . o . . . o o . . . . . O + $ ; 9 m T ;.7.h.z.N.C.Z.C.M.z.h.7...T m 9 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+.1 1 1 , , , , , , , , , , , , , , N Z.Z.Z.Z.Z.Z.B.w > , , , > > > > , : > > > > > > : , > : - > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z._ : - - & - - - - - - - - & - V Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.n.' v v c - & % & # & % # % % # % % # % % # # $ % @ % # # # # # @ # @ @ - - @ + O - O o + + @ + - - + # + # @ $ # # ; ; 0 f A Q ..<.2.7.9.9.2.<. .Q A f 1 : * % @ + + X + X + O + O O O O O X O O O + O O O O O O o . o . . o . . . . . o . O O % ; e m T -.8.h.z.N.Z.Z.C.N.x.h.8.:.T m 9 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 1 1 2 2 1 1 1 p.Z.Z.Z.Z.Z.p.1 1 , 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., , 1 , 1 , , 1 , 1 , , , > , , > , B.Z.Z.Z.Z.Z.Z.k.I F D F F F F N > : > : > : > : , : : > > : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: - : : : : : : - - - - & - - 0.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.u.u.u.u.s.d.d.d.d.d.d.t.=.O.v v v v ; % # % # % % % % % & % % % % # & # # % @ % % # # # # @ # @ # @ @ O @ + - O - + @ - + + + + @ @ @ + @ $ # - ; 1 t B Y .1.9.w.j.j.j.f.9.1. .T M r < = % + + + + O + O + O O + + O + X + X X X O O O O O O O X . . . . . o . . . X o . . . O $ $ = 9 m T ;.7.h.l.M.C.C.C.M.x.h.7.;.K m 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 2 1 n Z.Z.Z.Z.Z.Z.&.1 1 1 1 1 1 , , Z.Z.Z.Z.Z.Z.+.1 , , , , , , , , , , , , , , , , , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.v.W > > > > : , : : > : : > > : O.Z.Z.Z.Z.Z.Z.Z.Z.Z.O.- : - : & : & - - - - - - - 5 Z.Z.Z.Z.Z.Z.Z.Z.Z.4.= & & & ; c v v v v v v v v v v v v k - & & # & % & % % % % % % # % # # & % % % % @ # # # # @ # # @ - O - @ + - + + @ @ @ + + - + + + @ @ @ @ # - ; 1 n H ^ 1.9.j.l.x.x.x.l.j.9.,.^ S b 7 ; % $ + + O + + O O + + O O + X O o X X + O O O O O O X X . . . . . . o . O O O + $ = 7 b K .2.f.l.m.M.N.M.m.l.f.2. .K h 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 1 2 2 2 1 0.Z.Z.Z.Z.Z.Z.W 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , 1 1 1 , , 1 , , , , , , , , , > d Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.! ; > > : : : > , : : : : : d Z.Z.Z.Z.Z.Z.Z.Z.Z.d : - : : & : : & : : : - - - I Z.Z.Z.Z.Z.Z.Z.Z.B.< & & & & - v v v v v v v v v v v v v q % % % % & % % % % & % % % % # & # # # # # # # # # # # # @ # # + + - O @ @ - + @ @ @ + - O + + @ @ @ @ @ # - ; e m Y -.2.q.l.x.M.N.M.m.l.q.2...Y m w : % % + O + + X + O O + + O O O O O + o o X X O O O O . O . . o o . . o o . . o . . O + $ * 6 s S R >.8.h.l.z.x.z.l.g.8.>.! S r 5 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.[ +.+.+.+.+.p.Z.Z.Z.Z.Z.Z.B.1 1 1 1 1 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , > , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.t > > , > , : : > : , > : : 6.Z.Z.Z.Z.Z.Z.Z.6.: - : - : : : & : : & & - & & o.Z.Z.Z.Z.Z.Z.Z.Z.4.& & & & & 4 v v v v v v v v v v v v v ; % % & % & % % & % # % % % % % # # # # # & # # # # # # # # @ @ @ @ @ @ - @ + O @ @ @ @ @ + - + @ + + @ # # - < e B Q ;.7.h.x.N.C.Z.C.M.x.j.7.;.R M e < ; # + + + X + O + X O O + + O + O X O O + O O o O O . O . . o o . . . . . . . . . O X $ * ; e b Y { <.8.f.g.j.h.f.7.<.{ Y b w ; $ + . ", +"2 2 2 r 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.+., 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , , , , , , , , 0 k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.0.> > , : : : : > : : : , : 4.Z.Z.Z.Z.Z.Z.Z.4.: - - : & - : : & - & : - - & 0.Z.Z.Z.Z.Z.Z.Z.Z.E & & & & & q v v v v v v v v v v v v v - # & % % % % % % % % % & % % % # & & # # # # # # # # # # @ # @ - @ @ @ O O @ - + + @ @ + + + + @ + @ @ # @ ; < r B Q >.9.j.x.N.C.Z.Z.N.x.j.9.>.Q B e < = + @ + O + O + O + O + O O O O O O O + O O O O O O . . o . . o . . . . O . . O X + $ = 7 s C U .>.2.7.9.7.2.>.{ Y M r 5 * $ O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 7 2 2 1 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 1 , 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , 1 1 , 1 , , , , , , , , , > , , , , w 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.B.> - : : , : , : > : : : 7 B.Z.Z.Z.Z.Z.Z.Z.B.7 : : - : : & & : : : & & : & p.Z.Z.Z.Z.Z.Z.Z.Z.D - & & & * i v v v v v v v v v v v v z # & % % % & % % % % % % # # % % # # # # # # # # # # # # # # # @ + @ - O + - @ @ - + + # - + - o + @ @ @ $ - ; ; t B R ;.9.h.x.N.C.Z.C.N.x.j.7.:.Y M e < * # # + + + O X + O + O O + O + O O O O O O O o O O . . . . . o . . . . o . o X X X $ % = 7 f C K ! .;.:.;.{ ! K C s 7 ; % + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.V 1 1 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , 1 , , , , , > , , , > , > , , 0 F F F F F F W 5.Z.Z.Z.Z.Z.Z.Z.I : > > : > > : > > : > | Z.Z.Z.Z.Z.Z.Z.Z.Z.} : : = : : - - : : & : : & : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & # a v v v v v v v v v v v v z - # & # & # - # # # & # % % % % # % # # % % # # # # # # # # # # @ # # @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ + @ * & < 9 M U -.2.w.l.m.M.N.N.x.l.g.2...K M w : = $ + + + + + O O + O O + O X O O X X X O O O O X O o o o o o . o . . . . . o o . O + $ * 3 7 r b S K T R K K A b r 7 * ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.B.6.n 1 1 1 1 1 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , , , , , , ; , , , > > > > > > , I Z.Z.Z.Z.Z.Z.+.> : > : > : > : : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: : : : & - - : & : & : - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & - & - & p v v v v v v v v v v v v z # # # & # & # # & # & # % % % % # % % % # # # # # @ # # @ % # # # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ # # > 2 b H ^ 1.9.j.l.x.x.x.l.h.9.,.^ S f 7 ; = + + + O O O + + X + X + O + O O + o + O O O O X O X X o o X o . . . o o o . . . X O + + $ % = 5 w r b m M m f r e 6 ; * ", +"2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 , 1 1 , , , , , , , , , , > , , > > ; , , , , > > , > > > > b.Z.Z.Z.Z.Z.0.> : > > : > : : > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.I : : : & : - & : : & & = : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & g v v v v v v v v v v v v g # - # & & # - - # # # & % % % % % % % # % # % # # % # # # % @ # @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ # * ; 1 r B T ..1.9.q.h.j.j.q.9.1. .Y M r < = $ + + + O + + O O + O + O + O O O O X o O O O O O O O O O . o o . . . X . X . O O O X $ % * ; 7 7 7 9 9 8 5 ; * + + ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , , , , 1 , , , 1 , , , , , > , , , > , > > , > , > > , > 5.Z.Z.Z.Z.Z.p.> > > : > : > > : : p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- - : : = : : : & : - - & p.Z.Z.Z.Z.Z.Z.Z.Z.V & - & & - p v v v v v v v v v v v v p - # - # # & # # & & # # % % % % % # # % % % # # # # # $ # @ @ $ @ # # @ @ # @ @ @ @ @ + @ @ @ @ # + @ + @ % # = , w f A Q ..1.2.7.9.9.2.<. .Q A b 7 ; = # + + + + O + + + O + O O O O + + O O O O X O O X O O X X O . O . . . o . . . . . O O X $ + % % % = ; ; * * * $ % ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , 1 1 , 1 , , , , , , , , > , > , , > , > , , > , : > > +.Z.Z.Z.Z.Z.u.: > > > > : > : : d Z.Z.Z.Z.Z.Z.u.Z.Z.Z.Z.Z.Z.t - : : & : : & : & & - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p - # - - & # - # # & & # & % % % % % % # # # # % % @ # @ % @ % @ # @ @ # @ # @ @ @ @ @ @ @ @ @ + + + @ + + # % # - < w n A R ^ ..>.>.>...^ Y A f 9 < = # % + + + O + O + O + + O + + O O O + X o X O O O O O O X . . o o . . . . O . . . + + $ $ $ $ $ $ $ $ $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 7 1 1 1 2 2 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , , , , , > , > > > > > > , > > +.Z.Z.Z.Z.Z.p.> > : : > > : > , %.Z.Z.Z.Z.Z.Z.j v.Z.Z.Z.Z.Z.4.- : & : : - - : - - - - u.Z.Z.Z.Z.Z.Z.Z.Z.Z & & - & & p v v v v v v v v v v v v p # # # # # & # % & # # # % % % % # # # % # % # % # # # % @ # @ # @ # # @ # @ @ @ @ @ @ @ @ + @ + @ @ + # @ # # % = - 1 e f B H Y Y Q Y Y S M y e 5 ; # % + + + O O + + O O X O O O O O + O O o + X X O O O O O X O O o . . o . o . o o X o X . . . O X X O + + + + O X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , , 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , , 1 , , , , , , , , , , , , , , > , > , , > > > , : , +.Z.Z.Z.Z.Z.u.: > > : > > > : 1 B.Z.Z.Z.Z.Z.b.: %.Z.Z.Z.Z.Z.B.7 : : : & - - - - : & : p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p # - & % - # % % # # & & % % % % % % % # # # # # # # @ % % @ @ $ @ @ @ @ @ @ @ @ @ # @ @ @ @ + @ # + # + @ + @ % # = ; < 0 t f m B B B m f r w < = % % % + + + + + O + + + + O X O O + O + O o o O + O O O O O O X o o . . o . . . o X X . . X X . . X . O . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.&., 1 , 1 1 , , , , 1 , , , , , , , , > , , , > , > > , , > > , , u.Z.Z.Z.Z.Z.%.> : > > : : : : ` Z.Z.Z.Z.Z.Z.| : d Z.Z.Z.Z.Z.Z.} : & & : - - : & - - & u.Z.Z.Z.Z.Z.Z.Z.Z.F & & & & & p v v v v v v v v v v v v p # - # # - # & % # & # # % % % % % # # # % # % # $ # % @ @ % @ % @ @ + - @ @ @ @ @ @ @ + @ @ @ # + # + @ + @ + + # % & ; > 7 0 w e r e e 1 < - ; * % + + + + O + + + O + + O + + O + O O O O O O O O O O O X X O X o . . o . X O . . . O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 b.Z.Z.Z.Z.Z.k., 1 1 , , , , , , , , , , , > , , , , , : , , : , > , > > > > 0 Z.Z.Z.Z.Z.Z.| , > : : > : > : v.Z.Z.Z.Z.Z.Z.t : : k.Z.Z.Z.Z.Z.v.: : & : : & : : - : & p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v i = % % & # % & # - - @ - + - + - % % % % # % # # % # # # # # # % @ @ # @ # @ @ @ @ @ @ + @ @ @ + # + @ @ + + @ @ @ # # # - - ; > , > < > - ; % # # @ + + + + + + + + + + $ + + X + O + O O X O O X O O O O O O O . X O O X X X X X O + + X X X X X . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.f.1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.Z.Z.Z.Z.Z.Z.J , , , , 1 , , 1 , , , , , , , , , , , , , , , > , > , > > , X.Z.Z.Z.Z.Z.Z.h > > > > > > , D Z.Z.Z.Z.Z.Z.k.: : : } Z.Z.Z.Z.Z.Z.I : : & & : & & - & - u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p % # & # # & # & + + - + - + - + % # % # # % # # # # # # # @ + # - # @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + # @ + + @ @ @ # # # # # - ; & ; % * # $ @ $ + + $ + + + $ + $ % $ + @ $ + @ + + O X + O + X + O O O X X . O O O X X O X O + + + $ + + + O O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 [ Z.Z.Z.Z.Z.Z.k.e , 1 1 , , , , , , , , , , , , , , , , , , , , > , > > > m B.Z.Z.Z.Z.Z.v.> > > > > : : > r.Z.Z.Z.Z.Z.Z.X.: : : d Z.Z.Z.Z.Z.Z.u.& : : : : & : & - & p.Z.Z.Z.Z.Z.Z.Z.Z.k.u.u.u.u.u.s.d.d.d.d.d.d.d.d.d.d.d.d.s.u.$.% & & # & # - + + - + - + - % # # # % % # # # # # # # # % # + @ @ @ @ @ @ @ # @ @ @ + # + # # + @ + @ @ @ + + + + # # @ @ # # # @ $ # $ @ @ + + + + + # @ $ * # * = & * * @ @ + + + + O O O O O O O O O O O . . O O O O + + $ $ $ * $ * $ $ $ + + . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 1 1 1 , 1 e B.Z.Z.Z.Z.Z.Z.B.p.p.p.p.p.p.i.i.i.i., , , , , : N i.i.i.i.i.u.p.u.p.p.p.Z.Z.Z.Z.Z.Z.Z.O.: > > : : > > t Z.Z.Z.Z.Z.Z.Z.7 : : : - k.Z.Z.Z.Z.Z.Z.e : & : & : : - : & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.& % # & # & + - - + - @ - + % % # % # # % # % # # # # @ @ @ @ @ @ @ # @ # @ @ @ + @ # + # + + # + @ + + + @ @ @ + @ @ @ @ @ @ @ @ + @ + + + + + + @ @ @ * = ; > : 5 : ; = & # # % + + + O O O O O O X O O o . O O O + + $ % * * * ; = = = * * $ $ + O X . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , F Z.C.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.M.1 : > > > > : > %.Z.Z.Z.Z.Z.Z.r.: : : : : ` Z.Z.Z.Z.Z.Z.4.- - : : & & - : & p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.% % - - - - - @ - + O $ - - % % # # & % # # # # # # @ # @ # @ @ - # @ @ @ @ @ @ @ @ @ @ + @ + @ + + @ + @ + + + @ + + @ @ + $ + + $ + + + + + + + # * ; > 5 7 e w e e 9 7 5 : * * + + + + X O O O O O O O O O O + + $ $ % = : 5 9 9 e 9 9 5 ; * * @ X X X ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 e k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , > , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : : > > : > > 7 B.Z.Z.Z.Z.Z.Z.` : : : : : 7 Z.Z.Z.Z.Z.Z.B.7 - & : & : - & & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.% % + $ + O @ - + - - + - + # # # # # # # # # # # % # # # @ @ @ + @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ @ + @ + @ @ + + + + + + + + + + + + + + + @ # $ % = > 0 e f m M M C b f e 9 : & $ $ + + X O O O O O X X O O O + + $ = = 6 e r b b C b b f e 6 ; & $ $ X ", +"2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 2 1 1 1 , 1 , 2 1 1 1 , 1 1 1 , , C k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , > , , , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : , : , : > : > ` Z.Z.Z.Z.Z.Z.B.7 : : : : : : r.Z.Z.Z.Z.Z.Z.} - & : : & - & - p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.- ; - - ; - - - - @ ; - - $ % # # # # # # # % % # # @ # # # - + @ @ # # @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ + @ + + @ + @ + + + + + + + + + @ $ * = < e s B G U R R T K G M s 9 5 = $ $ + O X X O X O O O X O + + $ * > 9 s m S K T T T K G m r 7 ; * $ X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 p.p.p.p.p.p.3.1 2 2 1 2 1 1 1 1 1 1 1 2 2 1 , 1 1 1 1 1 1 1 , 1 1 , [ 0.p.p.p.p.p.p.p.p.p.p.p.p.p., , , , , > N p.p.p.u.u.u.p.u.p.u.p.p.p.p.&.d , , : , : > > > : %.u.p.u.p.u.p.+.: : : : : : - I u.u.u.p.u.u.4.- : : & : - - & I B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.; 4 3 ; 3 3 ; 4 8 ; 4 4 ; 4 , > 4 4 4 4 4 < 3 3 3 3 3 3 3 3 - + @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ @ + + + # + # + + + + $ + + + + + + + @ # ; > 0 f A K ! { ;.>.:...! Y A f w : * $ + + + O O O O O O O O + $ * : 7 s M Y ! .;.:.-.{ R Y C s 7 = % $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 2 1 , 2 , 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , 1 , , > , , , , , , , , , , , , > , > , > > > > > , > : , , : , > , : : > > : : : , : : : > : : : : : : : : : : : - : : - : : & : & : - - - - - & V D V V V V V V V N V V E ] ] ] ] ] ] ] ] ] ] ] ] ] ] ' v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; O - o O - O O + $ O + - + - O @ @ + @ + @ + @ + + + @ + + @ + + @ + + + + + % + = : 7 f S T ..<.2.8.9.7.2.<.{ R B y 7 : * + + O O O O O X O + + + # : 7 s A Y { >.2.8.8.8.2.>.{ T A s 5 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 , 1 2 , , 1 1 , 2 , 1 , 1 , , , , 1 , 1 , , 1 , , , , , , , , , > , , > , , , > > , > , > > > > , : : > , : : , : > > : : > : : > : : : > : : : : : : : - - - : : & & : & : : & - - & - & - & - - & & - & - - & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - o - - + + - O - - $ O + - + + @ @ + @ + + @ @ + @ + + + + + + + + + + + + + * = 5 e M K .1.9.g.h.h.j.q.9.1.{ Y M e > & @ + + O O O O O O O + @ * : e b U { <.7.f.h.h.h.f.8.1.{ K b e ; % X X . . ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 , , , , , , , , , , , , , , , , , , > , > > , > , > , > > > > > , , , : : > > : > : > : > : : , : > : : : : : : > : : : : - : - : : : : : & : : - - - - - - - & - & & - - & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ - o - O O - + + - + + @ O + + @ + @ @ + @ + + @ + + @ + + + + + + + + + + % # : 7 b S ! <.9.h.l.x.m.x.l.g.9.>.~ A b 7 = % + + X O O O O O O + % = 5 s S ! >.8.h.l.z.m.z.l.h.8.>.R S s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 2 1 2 1 1 1 1 1 1 2 2 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 1 1 , , , 1 , , , , , , > , , , , , , , > > , : , > , > > : , : : , : : , > > > : : > : : : : > : : : > : : : : : : : - : : & : & : & : & & - & - - & & & & & & - & & & & & ; i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 O o - O - + O - o o + @ @ @ + @ @ + + + @ + @ + + @ + + + # + + + + + + + + # * > e m Y ..2.g.l.m.M.V.M.m.l.w.2.-.U b 7 ; % $ + O O O O O O + $ $ : 7 b U { 2.f.l.m.M.N.M.m.l.f.2.{ K b 7 * $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , > , > , , > , , > > > > > , > , > , > : , , : > : > > > : > > : > : : : > > : : : : - : : : : & : : & : : & : : : - - - & - & - - : & & & - & & & & & p v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ O - o - O - @ @ @ @ @ - O + + @ @ @ @ + @ + # + + @ + + + + + @ + + + + # $ & 5 e M T :.8.h.x.M.C.C.C.N.x.h.8.:.T m w : * $ + + O O O O X + + $ : w b R -.8.h.z.N.C.Z.C.M.z.h.7...T b e ; * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , > , > , , , , , , > > > > : , , > : , : , > > : > : : > : > : : : : : : : : : : : : - : : : : : & - : & & - - - - & - - & & - & - & & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - - O + o O - @ @ @ @ @ + @ @ @ + + @ + @ @ + @ + + # + + @ + + + + + + + @ % & > r M R >.9.h.x.V.C.Z.C.N.m.h.9.:.R M e > $ + + O O O O X O + + * 3 w M R ;.9.h.m.B.C.Z.C.N.z.j.8.:.R b e ; % + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 1 1 2 , 1 1 1 , 1 1 , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , > > , , , , > > , > > , > > > , : : , : , : : : > : > > : : : : : : : : : : : : : - : : : : - : & : : : : : & & - - - - & & - & & & - & & & & - & u v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 o - - - - O O + - @ @ O - + @ @ @ @ + + @ + @ + + + + + + + + + @ + + + $ + @ = 5 e M R :.8.h.x.N.C.Z.C.M.x.j.7.;.T C e > * + + O O O O O O + + % ; w b R -.8.h.z.M.C.C.C.M.x.h.7.-.T b e = $ + . . ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , , > > , , > > , > > > , : , , : , : , : > : : , : : : , > > : > : : : : : : : : : - : - : & : & : & : & - - - & - - & & - - - & - & - & % - ; v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 - o O O + + - + O @ @ + + @ @ + + @ @ @ + @ + + @ @ + @ + @ + + + + + + + + @ * : e b K ..2.w.l.m.M.V.N.m.l.q.2. .K m 9 : # $ O O O X O O X O $ $ ; 7 b Y { 2.f.l.m.M.B.M.m.l.f.2.{ K f 9 * $ + . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , , , , , 1 , > , , , , > , , , , > , > > , > > > > : , , > : > > : > > > : > > > : : > > : : : : : : : : : - : : & : : - : - : : & : - & : & : - & : & - & & & & - & & & & - u p g z l l l l l l l l g l l k g l k k k k k k k k k k l l k l k k k k k k k k k k k k ; @ # @ # @ @ @ - + + - O O + @ @ @ + + @ + + @ @ + + + + + + + + + + + + + + % % : 7 f S ~ <.9.h.l.z.m.z.l.g.8.>.! G f 7 = $ + O O O O X O X + + $ * 7 s S ! >.8.h.l.z.z.z.l.h.8.>.! A s 5 % $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , , > , > > > , > > > , > > , > : : , , : > > : > > : : : > : : : > : : > : : : : : : : : : : & - : : & : : & - - & : & & : & - & & - & - & & & & & & & & & & & - & & & % % & - # - - - - @ - - @ - @ - @ - # @ - + - # - @ + + - + - # + # @ @ # @ @ @ @ @ @ + + + O + - - + @ + @ @ + @ + @ + @ + @ @ @ + + + + + + + + + @ $ = 5 r M T ..1.9.q.h.h.h.f.9.1. .T m e 5 * @ + + O O O O X + O + $ & : e M Y { 1.8.f.h.h.h.f.8.1.{ U b 9 5 * $ ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 2 1 1 2 2 1 1 1 1 1 , 1 1 1 1 , , 1 1 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , , , > , > > , , , > , , > > > > > , > , : : , , : > : > > > > > > : : : : : : : : : : : : & : : : : : & : : & : : : & : - : & & & - & & & & - & & & - & & & & - # % & % % & & & # - @ - @ + + - @ @ - + - + - - @ - + - # + - - + - + + + - - + + - O @ # # @ @ @ - - o - @ @ O + @ @ + @ @ @ + + + @ + + + + + @ + + + @ + + + # $ * : 9 f A T ..<.2.8.8.8.2.>.{ T A s 7 = * $ + O O O O O O O O + $ $ = 7 r A Y { >.2.8.8.7.2.>.{ T C s 5 = $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 2 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 , 1 1 , , 1 1 1 , , 1 , , , , , , , , , , , , , > > , > > , , > > , : , : , > > : > > > > : : : : : > > : : : : : > : : : - : : : : & : : & : - & & & : & & & & : & & - - & & & & & - # & - # & - # & & & & & # & & # - @ - - - + - - + - @ - + # + + - + # - @ + - @ + - - + + + - $ @ @ # @ @ @ @ + + + @ @ + @ @ + @ @ + @ + + @ + + @ + + @ + + @ + + + + + + + $ % = 5 e f A K ! ..;.>.;.{ { Y A f 9 5 = # + O O O O X O O X O O X $ & ; 7 s C U ! { ;.:.;. .! U C s 7 ; % $ X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , > > , > , , > > > > > , : : , : , > > > : > > : : : : : : : : : > : : : : : : : & : : : : : & : & & : - - - : - & & - - & & - - & & & & - - & & & & - & # % & # & # & - @ - @ - @ - # @ - + - @ # # - # - + - + @ + - - + + @ - + + + @ # @ # @ @ @ @ @ @ @ + + @ @ @ @ + @ @ + @ + @ + @ + + @ + + + + + + + + + + + @ $ # = 5 9 s M S K T R T U S M f w 5 * @ + + + O O O X O O o O O + + % * : 7 s m A K T T T K A m s 7 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , > > , , , > , , > > > > , > > : , , : > : : , > > : > > > > : : : : : : : : : - : : : : : : & : & : : : : : : - & - & & : - & & - & & & & & & - # - # # & & # & & & & & & & # @ - @ - @ - @ @ - + @ @ - # - + # # # # @ - # + @ + - + + + - - @ $ - @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + @ + + @ + + + @ + @ + + + + + + + $ % % = 5 9 e b m M C C b f e 7 : = $ @ + O O O O O + O X O X X + + $ = ; 7 e s b b m m b r e 6 = * $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 1 1 1 1 , 1 , , , , , 1 , , , , , , , , , , , > , , , , > > > > , , > > > , , , : > , , : : > > : > : : > > > : > > : > : : : : : : : : & : : & : - : & : & - & & - - & & - & - & - - & & & & & - & & & & & & & # & & # & % - @ - @ - + @ - # @ - @ - @ - # # # + # - # - + + - - @ - + + + - @ + + @ @ @ @ @ - @ @ + O @ + @ + @ + @ + + @ @ + @ + + @ + + + @ + + + + + + + + @ $ % = : 5 7 e e e e w 7 5 ; * # % + + + O O O O O O O O X X O O + $ $ * = 5 6 9 e w w 9 6 3 * * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , , , 1 , , 1 , , , , 1 , , , , , , , , , > , > , , > > , > > , > > > , : : , : : , : : > : > > : : > : > : : : : : : : : : : : : : : : : : & & : & : & : - - & - - & - & & & & & & - & & - # & & & & # & & & & & % & @ - @ - # - - @ - - + - # # @ @ - # - # + # # # - + + + - + - + + # @ # # @ @ @ + O @ @ @ - + @ @ + @ @ + @ + @ + @ + + + + @ + + + + + + + + + + + + @ @ % * & : 3 : > : : * = & $ $ + + O + O O O X O O O O O . X O O X + + % & * = = = ; = = * $ . $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 1 , , 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , : > > > > , , : : , : , : > > , : : > : > : : : : : : : : : : : : : : : : - : : - & : - : : & : & & : & & & : & - & & & - & - & & & & & & & & & & # & & & & # & # & # & & & # & # # & & @ # & @ # @ & @ @ & @ & @ @ @ @ @ @ @ & @ @ @ @ @ # @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + + @ + @ + + + + @ + + + + + + + + + + @ + @ @ # % % & % & & # @ @ @ + + + X X + O O O O X O O O O O O O O + + $ $ $ * $ * $ + $ + O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 1 1 2 2 2 1 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , : , , , : , , : > > , : , > : , > , , : : : : : > > > > > > : > > : : > : : > : - : : - - : - & : : & & - - : & : : & & : & & - & & & & & & & & & & & & & & # & & & & # & & & & # # & # # # & # & # # # # & @ & # % # # % & @ # # @ & # @ # # @ @ @ @ @ # @ @ @ @ # X @ @ @ @ @ + @ + @ + + @ @ + + + @ + + + + + + + + + + + + + + + o @ @ @ @ # # # @ @ + @ + + + X o o o o O O O O O O X X O O X X O O + + + + + + + + + + O O . . ", +"2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , , 1 1 , , 1 , , , , 1 , , , , , , , , , , , , , : , > , , , > > , : : , : , , : , : , , > > : : > : > : : : : : : : : : : : : : : : - : : : - : : & - & : & : : & : : & - & - & & & & & & & & & & & & # & & & & & & # & # & & & & & # # # & & # @ & @ & @ @ # @ % # @ @ @ @ # # # @ @ @ & # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ + + + @ + + + @ @ + @ + @ + + + + + + + + + o + + X + + + @ + + + @ + + + + + + X o O O o X X O O O O O O O O O O . X O O . O O + + . O + . O o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , , 1 1 , 1 , , 1 , , , , , , , , , , , , : , , , > , , , > , , , , : , : : : , , : : > : > > : > : > : > : > : : : : : : : : : - : - - : : - : : : : & : & & : & : & & & - & & - & - & & & & & & & & # & # & # & # & & & # # & # & # & # & # & @ & # # & # & # # # # & # # @ & @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ + @ @ @ @ @ + @ + + @ + + + + + + @ + + + + + + + @ o @ + + X o o + + o + + X + X X + o + O + X X + X O O O O X O O X X O . o O O . . . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , > , : : , , , : , , , : : , , : : > > : : > > > : > > : : : : : : : : : : : : : - : : - - - - & : & & & : & & & & : & & - & & & & & & & & & & & & & & & & & & & & # # # & & & # & # # # & # # & & @ & # # # % # # % @ # # # # @ @ & @ @ @ @ @ @ @ @ @ @ X @ @ # @ @ @ @ + @ @ + @ + @ + + @ + + + + + + + + + + + + + + + o + o + o + + o + X + + o O O O O O o o o O O O O O O O o o O O X O X o . . . . . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 2 2 1 1 1 2 2 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 1 , 1 , 1 , , 1 1 , 1 , , , , , , , : , , : , , > , , > , , , : , , , : : , , : , : , , : , , : : : > : : > > : : : : : - : - : : : - - - : - : : : : & : : & : : & : & : & - & & - & & & & & & & & & & & & # & & # & & & & & # # & # & # & # & & @ # @ @ @ & % # % # # & # # # # @ @ # @ @ @ @ @ @ @ @ @ # # @ @ X # X @ + @ + + @ + @ @ + @ + + + @ + + @ + + + + o + X @ + + + + + + + o + + + o o X + + O + o + O X O X O O O O O X o o X O O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , , 1 , 1 1 , , 1 , , , , , , , , , , , , , , > , : , , : , : , : : > , : : , : : : , : : > : > : : > : : > : : : : : : : : - : : - - - - : & : & : & : & : & & & - & & : & - & & & & & & & & & & & # & # # & # & & # & # & # & # & # % # @ # # & % # % @ # % # # # # # # @ # # @ @ & @ @ @ # @ @ @ @ # @ # X @ @ + @ + @ @ + @ + + @ + + @ @ + + + + + + + + + + + o o @ + + + X + + o o X o + + O O O O o + + o O O O O O O O X O O O O o X o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 , 1 , 1 , 1 1 , , , 1 , , , , , , , , , , , , , , : , > , , > , , , , : > , > , , , : , : , , : : > > : > : > : : : > : : : : : : : - - : - - : - : - & : & : & : & : & & : & & - & & & & - & & & & & & & & # & & & & & & & # & # & & # & # # # & & # & @ & # % % % % # # # % @ # # # # # @ # @ @ @ @ @ @ @ @ @ @ # X # & X @ @ @ @ + @ @ + @ @ + @ + + + + + + @ + + + + + + + X @ o + X + X + o + + + X o + O + + O O X o o O O O O X O X o o O X . . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , , , , 1 , , , , , , , , , , , , , , , : , : , > > > > > > > > > , : , : : > : : > : > : : : > : : : : : : : - : - : : : : & : & : & : & : & - - & - & - & - - & & & & & & & & & & & & & # & & & # & & # & & # # # & # & @ & # # @ & # # % # @ # # # # # @ # # # @ @ # # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ + + + + + + + + + + + X + + + + + X + + X + + + + + X + O O O O O + + X X O O O O O O X O . o . . X O O O O . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 1 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , 1 , , 1 1 , , , , , , , , , , , , : , , : , , , , , , , , , : > > > > : > : , : > > > > > > : : > : : : : : : : : : : : - : - & - - : & : : & & : : & & & - & - & & & & & & & & & & & # & & # & # & & & # & & & # # & & & & # & # & @ & & # # % % & # & # # % @ % # # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ # X # # X + @ + + + @ + @ + + + + + @ + @ + + + + + + + + + + + + + + X + + X o O O + X o + O O O O O + o O O O O O O X X . o o . o . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 1 1 2 1 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , > , , , , , > > : > > : , > > > > : , : : > > : : > : : : : : : > : : : : : : : - - : - : : : : & : : & : & : & : & : & : & & - & & & & & & & & & & & & & % & & & & & # & # & & # # # # & # # # & @ & & @ & # @ # # # % % @ & & X @ @ @ @ @ @ @ # @ # @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + @ + @ @ + + + @ + + + + + + + o + X + X + o + o X + + + O + o O O + + o + o O O O X + X O O o O O o o . . . O O . . o o O . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 , 1 , 1 , , , , , 1 , , 1 , , , , , , : , , , : , : , , : , > , > , > > > > : : , : > : > > > : > > > : : : : : : : : - : : : : - : & : : : : & : & : & : & & : & & : - & & - & - & & & & & & & & & & & # & # & # & & & # & & & & # # & & @ & @ @ & # @ & # # % @ @ @ @ @ & & @ @ @ # # @ # @ @ @ @ @ @ @ @ X @ @ @ @ @ + + @ + + @ @ + + @ + + + @ + + + + + + + + + + + + + + + + + + o + o + + + O + O O X O X O O O X O X X O O . O . o o . . . O . . o o ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , : , > , > > , : , , > > > > > > > > > > : : > > > : : > : : : : : : : : : : : - : : - : & : & - - : & & : : & : & & & & & & & : & & & & & & & & & & & & & & # & & & # & & # & & # & & # # & # & @ # # # # # # # # # # @ & & @ @ @ @ & @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + + + @ + + @ + + + + + + + + + + + + + + o + + o + + o O O + O X O O O O + O O O O O O O O O O O O O X X . . O o . o . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , > > , , > , > , > , , , : , : > > > > : > > : > > > : : : : > : : > : > : : : : : : : : - - : : & : : - - - - : & & : & : : & : & & & & & & - & & & & & & # & & & & & & # # & # & & # # & # # & # & # @ & & @ @ & & # & # % # @ @ @ @ @ @ @ @ # @ # # @ @ @ @ X @ @ @ @ @ @ @ + @ + @ @ + @ @ + @ @ + + + + + + + @ + + + + + + + + + + + + + O + + O + O + X + + O O o O O + O O O O O O O O O O O O O X o O o . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , 1 , 1 , , 1 , 1 , , , , , , , , , : , , , , , , > , > , > : , : , > > > > > > > > > > > > > : > > : > : : > : : : : : : : - : - : - - : - - - - & - & : & & & : & & & : & - & - & & & & & & & & & # # & # & & # & & # & # & & # & # # & # & # @ & # # # # # @ # % # @ @ @ @ & @ & @ @ @ # @ @ @ @ @ # @ @ @ @ @ X @ @ + @ + @ + @ + @ + + + @ + + + @ + + + + + + + + + o + + o + o + + O + O + O + O O O + O O O O O O O O O O O X o O O . O . X O o o o o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , , , , > , , > , , > , > , > , , , : > > > > > > > > : : : > > : > : : : > : : : : : : : : : - : - : : - - : - - : - : & : & : & & : & & & & & & & & & & & & & & & & & & & & & & & # & # & & # & # & # # & # & # @ # & @ & @ # # # # & @ & @ @ @ @ @ # @ # @ # @ @ @ @ @ @ # X @ @ @ @ @ + @ + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + + + O O + O + O + O O + O + O + O O O O O X O X O O O . . O o O o . . . . . ", +"2 2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , , 1 , 1 , 1 1 , 1 1 , 1 , , , , , , , , , , , , , , : , , : , , : , , : , , , > , > > > : , : > > > : > : > : : > : : : > : : : : : > : : : : : - - - : : - - : - - - & : & & & : : - & - - & - & & & & & & & & & # & & & & # & # & # & & # & # & # & # # & # & # & & & # # & # # # # # # # # # # @ # # @ @ @ @ @ # @ @ @ @ X @ @ @ @ @ @ @ @ X @ X @ + @ + @ + + @ + + + @ + + + + + + O + + + + + + + + X O + O O O + O + O O o X O O O O O O O o o o X X o O X . O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 1 , 2 1 1 1 , 1 , 1 1 , , 1 , 1 , 1 1 , , 1 , , , , , , , , , , , , , , , , , > , : , : > , : , > , > > > > > > : > > : > : > : : > : : : : : : : : : : - - - - - - & : : & : & : : & & & & & & & - & & & & & & & & & & & & & # & & & & & & # & & # & # & # & # & # # # @ # # # # # # & # # # # # # # # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ X @ @ X @ + @ + + + @ + + @ + + + X + + + + + + + + + X o + O + + O + + O + O O O X + O o O O O O O O o O O O O o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 , , 1 1 1 1 , 1 , , 1 , 1 , , 1 , 1 , , , , , , , , : , , , , , : > , : , , : , : : , > > > : > > > : > : > : > : : > : > > : : : : : : : - - : : : - - : & : - - & : - & : & : & - & & & & & & & & & & & & & & & & & # # & & # & & # # & # & # & & # # & & # # & # # # # # # # # # # # @ @ # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ X @ @ @ + + + + + + + + + + + + + + + + + + + O o + + + + O + O O O O o O O O + + O O O O O O O O X O O X O o o O . O O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 , 1 , 1 1 1 , 1 , , 1 , 1 , , , , 1 , , , , , , , , , , , , , , , , : , , , , , , : , > , , : , : > > > : : > > > : > : > : : : : : : : : : : : : : : : - - - - : - - - - : & : & & : & & & - - & & - & & & & & & & & & # & & & & & # & & & # & # & # & # # # & @ # & # # & # # # & # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ @ X @ + @ @ + @ + @ + + + + + + + + O + + + O + + X + o + + o + + + O + O O o O + O O X O O O O O X O O X O O O O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , > , , > , , > : , : , > : , , : , : > > > : : > : > > : : > : : : : : : : - : : : - : - : - : - - - - - & : & & - & : : & - & & & & & & & & & & # & & & & & & & # # & & & # & & # & # & & # # & # # # # # & # # # & # # # # # & # # @ @ @ @ # @ # @ @ # @ @ @ X @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ @ + + + + + + + + + + + + X + + O + O + o + + X + O O O O O O O O + X O O O O O O O . . o . O O O O o O O o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , > , , > , , : , > , , , : , : , : > > > > > > > > > > : > : > : : : : : : : : : : - : : - - - : - - - - - - : & & : & : & & - & & & - & - & & & & & & & & & & & # & & & & # # & # & & # & # & # & # # & # # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ X + X @ @ X @ + + + + + + + + + + + + + + + + + + + + o + o + X + O + o O + X X + + O O O O O O X X O O O . X O . o . o o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , , , > , > > > , , : , : , , : > , > > > > > > : > > : : > : > : : : > : > : : : : : : - : : - - : - - - - - - : & : & & & : & & & & & - & & - & & & & & & & & & & & # & & # & # & & # & # # & & & # # # # # & # % & # # # # # # # # # # @ # # @ # # @ @ @ @ @ @ @ @ X @ @ @ @ @ X + @ X @ @ X @ + + @ + @ + + + + + + + + X + + + + O + + + + + + O + + O + X O O O O O + + O O O O O O O O . . o . o o . O o O o O O o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 , 1 , 1 1 , , , , , , , , , , , , , , > > , , , > , : , , , : , : , , : > > > > > : > > : > > : : : : > : > : : : : : : : : - : : - : - - : - - - - & : & : : & & & : - & - & & & & & & & & & & # & & # & & # & # & & & # & # & & # # # # & & # & # % % # # # # # # # # # # # # @ @ # # @ @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + + + + + @ + + + + + + + + + + + + + X + o + X + O o O + o + O + O O O O O O O O O O O . . O X . . . . o o o O O o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , : , , , , > , , > , , , : > , : : , : > > , > > : > > > > : : > : > : > : : : : : : : : : : : - : : : & : : & : : & : & : & : : & & & & - & - & & & & & & & & & & & & & & # & & & # & & # & & @ & # & # # # # & # & % # # % # # # & # # # # # # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + @ + @ X + @ + + + @ + + @ + + + + + + O @ O + O + + + O + + X + O O + O O O O O X + X O O O O O X X o O O . . o . . . O o . . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , , 1 , 1 , 1 , , 1 , 1 , , , , , , , > , , > , > , > : , , , , , , : , > > > > > > > : : > > > > : : : : > : : : > : : : : : : : - : : : & : : : & : & : & : & & : & : & & & & & & & & & & & & & & # # & & & & # & & # & & # # & # & & # & & & & # # & # % # # # # @ # # # # @ # @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X X @ @ @ @ + @ + @ + + + + + + + + @ + + + + + + + + O + o + + + O + X + O O O + O X + X O X O O O O O O O o . . . o . . . . o o o . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , > , , , , > : , : , > : , , > > , : > > > > > : > : > : : > > : : > : : : : : : - : - - : - : : : & : & & : : & : : & : & & - & - & & & & & & & & & & # & & & # & & & & # & & # & # & # & # # # # # # # # # # % # # # % # # # # # # # @ # @ # @ @ @ # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ + + @ + @ + + + @ + + + + + + + + + X + + + + + O + + O + O O + X O + + O + X o + + o O O O X O X X o . O o . o o o o . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , : , , > , , , , > , > > , : : > > > > > > > > : > : > > : > : : > : : : : - : : : : - - : & & - : : - : & : & & & & & : & & - & & : & & & & & & & & & & & & & # & # & & & # & & # & # & & # & # # & & # # # # & & # # # # # # # # # # @ @ @ # @ @ @ @ @ @ X @ @ @ @ X @ @ X @ @ @ X @ + @ + + @ + + @ + + + + + + + + + + + O + + + + O O + + X + O + O O O + X O O O O O O O X O O X o o . . . . o . o . o . o . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , , , 1 , , , , 1 , , , , , , , , , , , , , : , , : : , > , > , : , : > : > > : : > > > : > : : > : : : : : : : : : - : : : : : : : : : & : & : : & : : & : & & & & & & - & & & & & & & & & & & & & & # # & & # & & # & # & # & & # & & # # # # # # % # % # # # # # # @ # # # # @ @ @ # @ @ # @ @ @ @ @ X X @ + @ + @ @ + + @ + + + + + @ + + + + + + + + + + + X + + + + + X + + X O O + O O O O O O O + o O O O + O O . . O . o o . . . . . . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 , , , , 1 , , , , , , , , , , , , , , , , , : , , : , : > : , : , > > > : > > : : > : > : : : > : : : : : : : : : : : - : : & : & : & & : & & : & : & & & & - : & & & & & & & & & & & # & & & # # & & & # & # # & & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ # @ # # @ @ @ @ @ @ @ @ # @ @ + @ @ @ + @ @ + + @ @ + + + @ + + + + + + + + + + + + O + X + + + X O + + O + X + + O + O O + X O O O O O . O . O . . o o . . . o o . . . O O ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 , 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 1 , , , , , , 1 , , , , , , , : , : , : , , , : , > > > : > , : > > > > > > > : : : > : > : : > : : : : : : : : & : : & : & : - : & : & & : : & : & : & - & & - - & & & & & & & & & & & & # & & & & & # & & & & # & & # & # & # & # # & & # % # # # % % # # # # # @ @ @ # # @ @ @ @ @ @ @ X # @ @ @ X @ @ @ @ + @ + @ @ @ @ + + + + @ + @ + + + + + + + + + + + + O + + O + + O O + + O O O + O O O o O O O O O O O . . o o . . . . . o o o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , 1 , , , 1 , , , , , , , , , , : , , , , , , > > , , > , , > , , : , > > > : > : > > > > : : > : > : : > : : : : : : : : : : : : - - : & : - : & & : & : & & - & & & - & & & & & & & # & & & & & & & # # & & # & # # & # # # & # & # # # & # # # # % % % % @ # # # # # # # # @ # @ # @ @ @ @ @ @ @ # @ @ # @ @ + + @ + @ + + + + @ + @ + + + + + + + + + + + + + + X + + O + + + O + + O O + O + O O O O O o O O O O O O . o . O . O o . . . o . o o O O ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 1 2 1 2 , 1 1 1 1 1 , 2 2 , 1 1 1 , 1 1 , , 1 1 , , 1 1 , , , , , 1 , , , , , , , , > , , > , > , > , : > , : , > : : , : > > > > > > : > > : : > : : : > : : : > : : : : : : - : - : - : & & : - & : : : & : & & : : & & & & & & : & & & & & & & & # & & & # & # & & & & # & # & # # & # # # & # & # # & # # # # # # # # # # # # @ @ - @ @ @ @ o - + o - @ @ @ @ @ @ @ + @ + + @ @ + @ + @ + @ + @ + + + + + + + + + + + + + + + + o + + X X + O + + X + + O O o O O O O O X X O X O X O o o O o O X X O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 1 2 1 1 2 1 2 1 1 2 , , 1 1 1 , 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , > , > , , , , , , : , , , > , > , : , > : > > : > > : > : : > : > : : : : : : : : : - : - - : : : : - : : & & & : : : & & : & : & & & & & & & & & & & & & & & & & & & & # # & & # & # & # # & & # # # & # # # # # & # # # # # # # # @ @ # + # @ o @ - o @ @ + @ @ @ + @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + X + + + o + o + + O + O O X X O O O + O O O O O + O O o X O O O O X O O X O o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 1 1 2 , 2 1 2 1 1 1 2 , 1 , , 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , , , , , , , , 1 , , , , > , , , > , > > , : , : : , , : > : , : : > > > > : > : > > : : : > : : : : : : : : : : : - : - : - : : & & : & & : & : & & & & & & : & & & & & & & & & & & & & & & # & & # # & & & # & # & # & & & # & & # # # # & # & # # # & # # # # # # # # + @ @ - @ - o @ @ @ @ @ @ @ + @ + @ @ + @ @ + + @ + @ + + + + + @ + + + + + + + + X X + + + + + + o o + O O O o + o X O O O + O O O O O O O X X o o O X o O X o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 2 1 1 1 1 2 1 1 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , 1 , 1 , , , , , , , , , , , > , , , > , , , > , , > > , > > : , > > > > > > : > : : > > : : > : : > : : : : : - : : - : : : & : : - : & : & : & : & : : & & & & & & & & & & & & & & # & # & & & # & & & # & # & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ + - @ @ @ o - + @ @ @ @ @ + o - + @ + @ @ + @ + + @ + + + @ @ + + + + + + + + + + + + + X + o + o + + O + + O + X + + o O O O O O O O O O O X X . . . . o O o O X . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 1 1 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , , , > > , , : , , , : > > , > , : > > : > > : > > : > > : > : : : : : : > : : - : : : - : & : : & : & : & : & : & & : & & & & & & : & & & & & & & & & # & & & & & & # # & & & # & # & # & # & # # # # # & & # # # & # # # # # # # # # # @ + + - o + + @ o + @ @ + @ @ + + @ @ + @ @ + + @ @ @ + + + @ + + + + + + + + + + + X + + + + + X + X + O + O o O X + O O O O O O O O O O X O o . o O . . o o o . o . X O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 , , 1 1 1 1 1 , , 1 , 1 , , , , 1 1 , 1 1 1 , , , , , , , , , , : , , , > , , : , > , > , : : , : > > : > > > > : > > : : > : > > > : : : & : : : - : - - : - & : - - - : : & & : : & : & & : & & & & & & & & & # & & & & & & # & & & & & & # & & & # & # # # & & # & # # # # # # # # # # # # # # # # @ # - + o - - @ @ - - o @ @ @ + @ @ @ + + @ @ + @ + + + + @ + + + + + + + + + + + + + + + + X + X + X + O + O + + o O O + + + O + O O O O O o X O . X o o O o O X O o . . O . O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 1 1 1 1 2 1 2 , 1 1 1 2 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , 1 , , , , , , , , , , , , , , , : , > , , > > > > , > , > : , : : , : , , : : > > : : : : > : > : : : : : : : : : : : - : : - : : & : & : & & & : & & : & & : & & : & : & & & & & & & & & & # & # & # & # # # # & # # & & & & # # # & # & # & # & # # # # # # # # # # @ # # @ + @ @ @ @ @ @ o - @ @ @ @ + @ + @ @ + @ + @ + @ + @ + + @ + + + @ + + + + + + + X + + + + + X + O + O + o + + + X O O O + O O O O O O X O X . . . . o X O X . o . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 2 1 2 1 1 1 1 1 2 , 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , 1 , , , , , , > , , , , > , , , , , , , , , : , : > , > , , : , > : > > > : > > > > : : : : : : : > : : : : : : : : - : : - : - : - - & : : & & & : & : & & & & & & & & & & & & & & & & & & & & & & & & & # & & # # # # & & # # & # # # # # # # # # & # # # # # # @ # @ - @ @ @ @ @ @ @ @ + @ @ @ @ @ # + @ @ @ + + @ + @ + + + + @ + + + + + + + + + + + + + o + + + X + O + O + o X O O + O O O O O O O O O O O O o . o . O o X . . . . O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 1 1 1 1 2 1 2 , 1 2 1 2 , 1 1 2 , 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , 1 1 , , , , , , , , , , > , > , , , > > > , : , , , > , > : , , : > : , > > : > : > > > : : : : > > : : : : : : : : & : & : : & : - - - - & : & : & : - & & & : & & & & & & & & & & & # & & # & & & # & # # & & # # & # & & # # & # # # # # # # # # # # # # # # # # # # # - o # @ @ @ @ @ + @ @ @ @ + @ + + @ @ @ + + + + @ + + + + + @ + + @ + + + + + + + + o + o + + + O + X + O O + + O + O + O + O O O O O O O O O O X . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 , 2 , 1 , , 1 1 , 1 1 , 1 , , 1 , , , , , , , 1 , 1 , , , , , , , , , > , , , > , , , : > , : > , : : , > > : > > : > : : : : > > > : : : : : : : : : : : : : : : : - : - - - - - & : & & & - - : & & & & & & & & & & & & & & & & & & # & & & & & # & & & # & # & # & # # & & # & # & # # # # # # # # # # @ # # - @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ + + @ + @ + + + + + + + + + + + + + + + + + o + X + + + + O O + O O O O O O O O O O X O O O X O X . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 2 2 , 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 1 , 1 , , 1 1 , 1 , , , , , , , , > , , , > > > > > : , : , > , , > , > > : : , > > > > : > > > : : : : > : : : : : : : : : : : & : : & - : & : - - - : : & - & & - & & & & - & & - & & & & & # & & & & & & # & # & & # & # # & # & # & # # & # # # # # & # & # # # # # # # # @ # @ o @ @ # # @ @ @ @ @ @ @ @ + @ @ + @ @ + @ + + + + + + + + + + + + + + + + + + o + + + o o + o + + O + O + O O O X + X + + O O + O O X O O O X O O X o o o o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 1 2 1 2 1 2 1 2 1 1 1 1 2 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , , > , , : , , > , : : , : , : , > : , : > : > : > : : > : > : > : : : : : : : : : : : : : : : & : : & - : & & : & : & - & : & : & & & & & & & & & & & & # & & # & & & & & & & # & # # & & # # & # # & # & # # # # # # # # # # # # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ @ @ + @ @ + @ @ @ + @ + + + + + + + + + + + + + + + + + X + O + O + + + O O O O O O O X O O O O O O O X X O . . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , , 1 , 1 , 1 , , , , 1 , , , , , , , , > , > > > , , , : , , : , > : , > , : > > > : > : > > : > : : > : > : : > : : : : : : : & : & & : : & : & & - & : & : - & - & - & - & & - & & & & & & & & # & & & & # & & # & # & & # & # & # # & & # # # # & # # & # # # & # # # # # # # # # # @ # @ # @ @ @ @ @ @ + @ @ @ @ @ # @ + + + @ + + + + + + + + @ + @ @ + + + + + + + + o + + + X + + O + + O + O + O + O O X O X O O O X o o O O o O O X o . o . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , , , , , , , , , , , , > , > , , : , , , > , : , : , > > : , > : : > : : > > : : : : : : : : : : : : : : : : : : : : - : : : : & : & - & & - & - & & & & & & & & & & & & & & & & & & & # & # & # # & # & # & & & # # & # # # # & # # & # # # # # # # # # @ @ @ # @ @ @ @ @ @ @ + @ @ @ @ + + @ + @ @ + @ + @ @ @ @ + + @ + + + + + + + + + + + o + + + o + + X O + O O + O O O O O O O + O O O O O O O o O O O o o o . o . . . . . ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 2 1 2 2 2 1 1 1 2 , 2 1 1 1 1 1 1 2 , 1 1 , 1 1 1 1 1 1 , 1 1 , , , , , 1 , , , , , , , , , , , , , , , , > , , : , > , : : , , : , : : , , : : > > > > : > : : > : > > : : : : : : : : : & & : : & & : - - & : & & & - - & - & - & & & - & & & & & & & & & & # & & # & & & # # & & # & # & # # # & # # # & # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + @ @ + @ + + + @ + @ + + + + + + + + + + + + + + + + + + + X + + + X O O + + O X O O O + X O X O O O O O O O O O O . . o o . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 2 1 1 1 1 , 1 , , , 1 , , , 1 , 1 , , , , , , , , , , > , , > , > > , , > , , > , > > , , : , : > > : , : > > : : > > : > : : : : : : : : : : : - : : : : & : : : & : - - : : & : & - - - & & - - & & & & & & & & & & & & & & & & & # & # & # & & # & # & # # & # # # & # # # & # # # # # # # # # # # # # # @ @ # @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + o + + o + o + + X X + O + O + O + O + O X O O O O O O O O O O O . o . . . . . o o " +}; diff --git a/Linux/Config.c b/Linux/Config.c new file mode 100644 index 0000000000..3f65524959 --- /dev/null +++ b/Linux/Config.c @@ -0,0 +1,137 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "Linux.h" + +#define GetValue(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%s", var); \ + } + +#define GetValuel(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%x", &var); \ + } + +#define SetValue(name, var) \ + fprintf (f,"%s = %s\n", name, var); + +#define SetValuel(name, var) \ + fprintf (f,"%s = %x\n", name, var); + +int LoadConfig(PcsxConfig *Conf) { + struct stat buf; + FILE *f; + int size; + char *data,*tmp; + + if (stat(cfgfile, &buf) == -1) return -1; + size = buf.st_size; + + f = fopen(cfgfile,"r"); + if (f == NULL) return -1; + + data = (char*)malloc(size); + if (data == NULL) return -1; + + fread(data, 1, size, f); + fclose(f); + + GetValue("Bios", Config.Bios); + GetValue("GS", Config.GS); + GetValue("PAD1", Config.PAD1); + GetValue("PAD2", Config.PAD2); + GetValue("SPU2", Config.SPU2); + GetValue("CDVD", Config.CDVD); + GetValue("DEV9", Config.DEV9); + GetValue("USB", Config.USB); + GetValue("FW", Config.FW); + GetValue("Mcd1", Config.Mcd1); + GetValue("Mcd2", Config.Mcd2); + GetValue("PluginsDir", Config.PluginsDir); + GetValue("BiosDir", Config.BiosDir); + GetValuel("Cpu", Config.Cpu); + GetValuel("PsxOut", Config.PsxOut); + GetValuel("RegCaching", Config.Regcaching); + GetValuel("Patch", Config.Patch); + GetValuel("VUrec", Config.VUrec); +// GetValuel("PadHack", Config.PadHack); + GetValuel("varLog", varLog); + Config.Lang[0] = 0; + GetValue("Lang", Config.Lang); + + free(data); + +#ifdef ENABLE_NLS + if (Config.Lang[0]) { + extern int _nl_msg_cat_cntr; + + setenv("LANGUAGE", Config.Lang, 1); + ++_nl_msg_cat_cntr; + } +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + FILE *f; + + f = fopen(cfgfile,"w"); + if (f == NULL) return; + + SetValue("Bios", Config.Bios); + SetValue("GS", Config.GS); + SetValue("PAD1", Config.PAD1); + SetValue("PAD2", Config.PAD2); + SetValue("SPU2", Config.SPU2); + SetValue("CDVD", Config.CDVD); + SetValue("DEV9", Config.DEV9); + SetValue("USB", Config.USB); + SetValue("FW", Config.FW); + SetValue("Mcd1", Config.Mcd1); + SetValue("Mcd2", Config.Mcd2); + SetValue("PluginsDir", Config.PluginsDir); + SetValue("BiosDir", Config.BiosDir); + SetValuel("Cpu", Config.Cpu); + SetValuel("PsxOut", Config.PsxOut); + SetValuel("RegCaching", Config.Regcaching); + SetValuel("Patch", Config.Patch); + SetValuel("VUrec", Config.VUrec); +// SetValuel("PadHack", Config.PadHack); + SetValuel("varLog", varLog); + SetValue("Lang", Config.Lang); + + fclose(f); + + return; +} diff --git a/Linux/GladeCalls.c b/Linux/GladeCalls.c new file mode 100644 index 0000000000..d8fa54ea0f --- /dev/null +++ b/Linux/GladeCalls.c @@ -0,0 +1,828 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "GladeCalls.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + + +void +OnDestroy (GtkObject *object, + gpointer user_data) +{ + +} + + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Gpu (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnDebug_Close (GtkButton *button, + gpointer user_data) +{ + +} + + +gboolean +OnDebug_ScrollBtn (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + + return FALSE; +} + + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Step (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Go (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Log (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLoggin_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data) +{ + +} + + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_GtkMenuItem_Language_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_item1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/Linux/GladeCalls.h b/Linux/GladeCalls.h new file mode 100644 index 0000000000..8c1a3db34c --- /dev/null +++ b/Linux/GladeCalls.h @@ -0,0 +1,411 @@ +#include + + +void +OnDestroy (GtkObject *object, + gpointer user_data); + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Gpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data); + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data); + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data); + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_Close (GtkButton *button, + gpointer user_data); + +gboolean +OnDebug_ScrollBtn (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_Step (GtkButton *button, + gpointer user_data); + +void +OnDebug_Go (GtkButton *button, + gpointer user_data); + +void +OnDebug_Log (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data); + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data); + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data); + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data); + +void +OnLoggin_Cancel (GtkButton *button, + gpointer user_data); + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data); + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data); + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data); + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_GtkMenuItem_Language_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_item1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data); + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data); + +void +OnMemWrite_Ok (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data); + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data); diff --git a/Linux/GladeFuncs.c b/Linux/GladeFuncs.c new file mode 100644 index 0000000000..c6ccdbe942 --- /dev/null +++ b/Linux/GladeFuncs.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "GladeFuncs.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists (".pixmaps", filename); + } + + if (!found_filename) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning (_("Error loading pixmap file: %s"), found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/Linux/GladeFuncs.h b/Linux/GladeFuncs.h new file mode 100644 index 0000000000..86a313454c --- /dev/null +++ b/Linux/GladeFuncs.h @@ -0,0 +1,61 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/Linux/GladeGui.c b/Linux/GladeGui.c new file mode 100644 index 0000000000..e01cf7fe3a --- /dev/null +++ b/Linux/GladeGui.c @@ -0,0 +1,3008 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "GladeCalls.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + +GtkWidget* +create_MainWindow (void) +{ + GtkWidget *MainWindow; + GtkWidget *vbox1; + GtkWidget *GtkMenuBar_Menu; + GtkWidget *GtkMenuItem_File; + GtkWidget *GtkMenuItem_File_menu; + GtkAccelGroup *GtkMenuItem_File_menu_accels; + GtkWidget *run_cd1; + GtkWidget *GtkMenuItem_LoadElf; + GtkWidget *separator2; + GtkWidget *states1; + GtkWidget *states1_menu; + GtkAccelGroup *states1_menu_accels; + GtkWidget *load1; + GtkWidget *load1_menu; + GtkAccelGroup *load1_menu_accels; + GtkWidget *slot_1; + GtkWidget *slot_3; + GtkWidget *slot_4; + GtkWidget *slot_5; + GtkWidget *slot_2; + GtkWidget *other1; + GtkWidget *save1; + GtkWidget *save1_menu; + GtkAccelGroup *save1_menu_accels; + GtkWidget *slot_6; + GtkWidget *slot_7; + GtkWidget *slot_8; + GtkWidget *slot_9; + GtkWidget *slot_10; + GtkWidget *other2; + GtkWidget *GtkMenuItem_Exit; + GtkWidget *GtkMenuItem_Emulator; + GtkWidget *GtkMenuItem_Emulator_menu; + GtkAccelGroup *GtkMenuItem_Emulator_menu_accels; + GtkWidget *GtkMenuItem_Run; + GtkWidget *GtkMenuItem_Reset; + GtkWidget *GtkMenuItem_Arguments; + GtkWidget *GtkMenuItem_Configuration; + GtkWidget *GtkMenuItem_Configuration_menu; + GtkAccelGroup *GtkMenuItem_Configuration_menu_accels; + GtkWidget *GtkMenuItem_PluginsBios; + GtkWidget *separator3; + GtkWidget *GtkMenuItem_Graphics; + GtkWidget *GtkMenuItem_Controllers; + GtkWidget *GtkMenuItem_Sound; + GtkWidget *GtkMenuItem_Cdvdrom; + GtkWidget *GtkMenuItem_Dev9; + GtkWidget *separator4; + GtkWidget *GtkMenuItem_Cpu; + GtkWidget *GtkMenuItem_Language; + GtkWidget *GtkMenuItem_Debug; + GtkWidget *GtkMenuItem_Debug_menu; + GtkAccelGroup *GtkMenuItem_Debug_menu_accels; + GtkWidget *GtkMenuItem_EnterDebugger; + GtkWidget *GtkMenuItem_Logging; + GtkWidget *GtkMenuItem_Help; + GtkWidget *GtkMenuItem_Help_menu; + GtkAccelGroup *GtkMenuItem_Help_menu_accels; + GtkWidget *GtkMenuItem_About; + + MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (MainWindow), "MainWindow", MainWindow); + gtk_widget_set_usize (MainWindow, -2, 200); + gtk_window_set_title (GTK_WINDOW (MainWindow), _("PCSX")); + gtk_window_set_position (GTK_WINDOW (MainWindow), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (MainWindow), FALSE, FALSE, FALSE); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (MainWindow), vbox1); + + GtkMenuBar_Menu = gtk_menu_bar_new (); + gtk_widget_ref (GtkMenuBar_Menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuBar_Menu", GtkMenuBar_Menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuBar_Menu); + gtk_box_pack_start (GTK_BOX (vbox1), GtkMenuBar_Menu, FALSE, FALSE, 0); + + GtkMenuItem_File = gtk_menu_item_new_with_label (_("File")); + gtk_widget_ref (GtkMenuItem_File); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_File", GtkMenuItem_File, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_File); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_File); + + GtkMenuItem_File_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_File_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_File_menu", GtkMenuItem_File_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_File), GtkMenuItem_File_menu); + GtkMenuItem_File_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_File_menu)); + + run_cd1 = gtk_menu_item_new_with_label (_("Run CD")); + gtk_widget_ref (run_cd1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "run_cd1", run_cd1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (run_cd1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), run_cd1); + + GtkMenuItem_LoadElf = gtk_menu_item_new_with_label (_("Load Elf")); + gtk_widget_ref (GtkMenuItem_LoadElf); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_LoadElf", GtkMenuItem_LoadElf, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_LoadElf); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_LoadElf); + + separator2 = gtk_menu_item_new (); + gtk_widget_ref (separator2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator2", separator2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator2); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), separator2); + gtk_widget_set_sensitive (separator2, FALSE); + + states1 = gtk_menu_item_new_with_label (_("States")); + gtk_widget_ref (states1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "states1", states1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (states1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), states1); + + states1_menu = gtk_menu_new (); + gtk_widget_ref (states1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "states1_menu", states1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (states1), states1_menu); + states1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (states1_menu)); + + load1 = gtk_menu_item_new_with_label (_("Load")); + gtk_widget_ref (load1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "load1", load1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (load1); + gtk_container_add (GTK_CONTAINER (states1_menu), load1); + + load1_menu = gtk_menu_new (); + gtk_widget_ref (load1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "load1_menu", load1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (load1), load1_menu); + load1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (load1_menu)); + + slot_1 = gtk_menu_item_new_with_label (_("Slot 1")); + gtk_widget_ref (slot_1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_1", slot_1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_1); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_1); + + slot_3 = gtk_menu_item_new_with_label (_("Slot 2")); + gtk_widget_ref (slot_3); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_3", slot_3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_3); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_3); + + slot_4 = gtk_menu_item_new_with_label (_("Slot 3")); + gtk_widget_ref (slot_4); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_4", slot_4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_4); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_4); + + slot_5 = gtk_menu_item_new_with_label (_("Slot 4")); + gtk_widget_ref (slot_5); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_5", slot_5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_5); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_5); + + slot_2 = gtk_menu_item_new_with_label (_("Slot 5")); + gtk_widget_ref (slot_2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_2", slot_2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_2); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_2); + + other1 = gtk_menu_item_new_with_label (_("Other...")); + gtk_widget_ref (other1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "other1", other1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (other1); + gtk_container_add (GTK_CONTAINER (load1_menu), other1); + + save1 = gtk_menu_item_new_with_label (_("Save")); + gtk_widget_ref (save1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "save1", save1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (save1); + gtk_container_add (GTK_CONTAINER (states1_menu), save1); + + save1_menu = gtk_menu_new (); + gtk_widget_ref (save1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "save1_menu", save1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (save1), save1_menu); + save1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (save1_menu)); + + slot_6 = gtk_menu_item_new_with_label (_("Slot 1")); + gtk_widget_ref (slot_6); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_6", slot_6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_6); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_6); + + slot_7 = gtk_menu_item_new_with_label (_("Slot 2")); + gtk_widget_ref (slot_7); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_7", slot_7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_7); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_7); + + slot_8 = gtk_menu_item_new_with_label (_("Slot 3")); + gtk_widget_ref (slot_8); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_8", slot_8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_8); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_8); + + slot_9 = gtk_menu_item_new_with_label (_("Slot 4")); + gtk_widget_ref (slot_9); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_9", slot_9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_9); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_9); + + slot_10 = gtk_menu_item_new_with_label (_("Slot 5")); + gtk_widget_ref (slot_10); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_10", slot_10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_10); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_10); + + other2 = gtk_menu_item_new_with_label (_("Other...")); + gtk_widget_ref (other2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "other2", other2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (other2); + gtk_container_add (GTK_CONTAINER (save1_menu), other2); + + GtkMenuItem_Exit = gtk_menu_item_new_with_label (_("Exit")); + gtk_widget_ref (GtkMenuItem_Exit); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Exit", GtkMenuItem_Exit, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Exit); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_Exit); + + GtkMenuItem_Emulator = gtk_menu_item_new_with_label (_("Emulator")); + gtk_widget_ref (GtkMenuItem_Emulator); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Emulator", GtkMenuItem_Emulator, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Emulator); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Emulator); + + GtkMenuItem_Emulator_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Emulator_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Emulator_menu", GtkMenuItem_Emulator_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Emulator), GtkMenuItem_Emulator_menu); + GtkMenuItem_Emulator_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Emulator_menu)); + + GtkMenuItem_Run = gtk_menu_item_new_with_label (_("Run")); + gtk_widget_ref (GtkMenuItem_Run); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Run", GtkMenuItem_Run, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Run); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Run); + + GtkMenuItem_Reset = gtk_menu_item_new_with_label (_("Reset")); + gtk_widget_ref (GtkMenuItem_Reset); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Reset", GtkMenuItem_Reset, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Reset); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Reset); + + GtkMenuItem_Arguments = gtk_menu_item_new_with_label (_("Arguments")); + gtk_widget_ref (GtkMenuItem_Arguments); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Arguments", GtkMenuItem_Arguments, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Arguments); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Arguments); + + GtkMenuItem_Configuration = gtk_menu_item_new_with_label (_("Configuration")); + gtk_widget_ref (GtkMenuItem_Configuration); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Configuration", GtkMenuItem_Configuration, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Configuration); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Configuration); + + GtkMenuItem_Configuration_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Configuration_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Configuration_menu", GtkMenuItem_Configuration_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Configuration), GtkMenuItem_Configuration_menu); + GtkMenuItem_Configuration_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Configuration_menu)); + + GtkMenuItem_PluginsBios = gtk_menu_item_new_with_label (_("Plugins & Bios")); + gtk_widget_ref (GtkMenuItem_PluginsBios); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_PluginsBios", GtkMenuItem_PluginsBios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_PluginsBios); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_PluginsBios); + + separator3 = gtk_menu_item_new (); + gtk_widget_ref (separator3); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator3", separator3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator3); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator3); + gtk_widget_set_sensitive (separator3, FALSE); + + GtkMenuItem_Graphics = gtk_menu_item_new_with_label (_("Graphics")); + gtk_widget_ref (GtkMenuItem_Graphics); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Graphics", GtkMenuItem_Graphics, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Graphics); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Graphics); + + GtkMenuItem_Controllers = gtk_menu_item_new_with_label (_("Controllers")); + gtk_widget_ref (GtkMenuItem_Controllers); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Controllers", GtkMenuItem_Controllers, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Controllers); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Controllers); + + GtkMenuItem_Sound = gtk_menu_item_new_with_label (_("Sound")); + gtk_widget_ref (GtkMenuItem_Sound); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Sound", GtkMenuItem_Sound, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Sound); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Sound); + + GtkMenuItem_Cdvdrom = gtk_menu_item_new_with_label (_("Cdvdrom")); + gtk_widget_ref (GtkMenuItem_Cdvdrom); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Cdvdrom", GtkMenuItem_Cdvdrom, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Cdvdrom); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cdvdrom); + + GtkMenuItem_Dev9 = gtk_menu_item_new_with_label (_("Dev9")); + gtk_widget_ref (GtkMenuItem_Dev9); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Dev9", GtkMenuItem_Dev9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Dev9); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Dev9); + + separator4 = gtk_menu_item_new (); + gtk_widget_ref (separator4); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator4", separator4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator4); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator4); + gtk_widget_set_sensitive (separator4, FALSE); + + GtkMenuItem_Cpu = gtk_menu_item_new_with_label (_("Cpu")); + gtk_widget_ref (GtkMenuItem_Cpu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Cpu", GtkMenuItem_Cpu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Cpu); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cpu); + + GtkMenuItem_Language = gtk_menu_item_new_with_label (_("Language")); + gtk_widget_ref (GtkMenuItem_Language); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Language", GtkMenuItem_Language, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Language); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Language); + + GtkMenuItem_Debug = gtk_menu_item_new_with_label (_("Debug")); + gtk_widget_ref (GtkMenuItem_Debug); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Debug", GtkMenuItem_Debug, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Debug); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Debug); + + GtkMenuItem_Debug_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Debug_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Debug_menu", GtkMenuItem_Debug_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Debug), GtkMenuItem_Debug_menu); + GtkMenuItem_Debug_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Debug_menu)); + + GtkMenuItem_EnterDebugger = gtk_menu_item_new_with_label (_("Enter Debugger ...")); + gtk_widget_ref (GtkMenuItem_EnterDebugger); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_EnterDebugger", GtkMenuItem_EnterDebugger, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_EnterDebugger); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_EnterDebugger); + + GtkMenuItem_Logging = gtk_menu_item_new_with_label (_("Logging")); + gtk_widget_ref (GtkMenuItem_Logging); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Logging", GtkMenuItem_Logging, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Logging); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_Logging); + + GtkMenuItem_Help = gtk_menu_item_new_with_label (_("Help")); + gtk_widget_ref (GtkMenuItem_Help); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Help", GtkMenuItem_Help, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Help); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Help); + + GtkMenuItem_Help_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Help_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Help_menu", GtkMenuItem_Help_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Help), GtkMenuItem_Help_menu); + GtkMenuItem_Help_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Help_menu)); + + GtkMenuItem_About = gtk_menu_item_new_with_label (_("About PCSX2")); + gtk_widget_ref (GtkMenuItem_About); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_About", GtkMenuItem_About, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_About); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Help_menu), GtkMenuItem_About); + + gtk_signal_connect (GTK_OBJECT (MainWindow), "destroy", + GTK_SIGNAL_FUNC (OnDestroy), + NULL); + gtk_signal_connect (GTK_OBJECT (run_cd1), "activate", + GTK_SIGNAL_FUNC (OnFile_RunCD), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_LoadElf), "activate", + GTK_SIGNAL_FUNC (OnFile_LoadElf), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_1), "activate", + GTK_SIGNAL_FUNC (OnStates_Load1), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_3), "activate", + GTK_SIGNAL_FUNC (OnStates_Load2), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_4), "activate", + GTK_SIGNAL_FUNC (OnStates_Load3), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_5), "activate", + GTK_SIGNAL_FUNC (OnStates_Load4), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_2), "activate", + GTK_SIGNAL_FUNC (OnStates_Load5), + NULL); + gtk_signal_connect (GTK_OBJECT (other1), "activate", + GTK_SIGNAL_FUNC (OnStates_LoadOther), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_6), "activate", + GTK_SIGNAL_FUNC (OnStates_Save1), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_7), "activate", + GTK_SIGNAL_FUNC (OnStates_Save2), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_8), "activate", + GTK_SIGNAL_FUNC (OnStates_Save3), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_9), "activate", + GTK_SIGNAL_FUNC (OnStates_Save4), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_10), "activate", + GTK_SIGNAL_FUNC (OnStates_Save5), + NULL); + gtk_signal_connect (GTK_OBJECT (other2), "activate", + GTK_SIGNAL_FUNC (OnStates_SaveOther), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Exit), "activate", + GTK_SIGNAL_FUNC (OnFile_Exit), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Run), "activate", + GTK_SIGNAL_FUNC (OnEmu_Run), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Reset), "activate", + GTK_SIGNAL_FUNC (OnEmu_Reset), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Arguments), "activate", + GTK_SIGNAL_FUNC (OnEmu_Arguments), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_PluginsBios), "activate", + GTK_SIGNAL_FUNC (OnConf_Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Graphics), "activate", + GTK_SIGNAL_FUNC (OnConf_Gs), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Controllers), "activate", + GTK_SIGNAL_FUNC (OnConf_Pads), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Sound), "activate", + GTK_SIGNAL_FUNC (OnConf_Spu2), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Cdvdrom), "activate", + GTK_SIGNAL_FUNC (OnConf_Cdvd), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Dev9), "activate", + GTK_SIGNAL_FUNC (OnConf_Dev9), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Cpu), "activate", + GTK_SIGNAL_FUNC (OnConf_Cpu), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_EnterDebugger), "activate", + GTK_SIGNAL_FUNC (OnDebug_Debugger), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Logging), "activate", + GTK_SIGNAL_FUNC (OnDebug_Logging), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_About), "activate", + GTK_SIGNAL_FUNC (OnHelp_About), + NULL); + + return MainWindow; +} + +GtkWidget* +create_AboutDlg (void) +{ + GtkWidget *AboutDlg; + GtkWidget *vbox2; + GtkWidget *packer1; + GtkWidget *hbox1; + GtkWidget *vbox4; + GtkWidget *GtkAbout_LabelVersion; + GtkWidget *frame1; + GtkWidget *vbox6; + GtkWidget *GtkAbout_LabelAuthors; + GtkWidget *pixmap1; + GtkWidget *frame2; + GtkWidget *vbox5; + GtkWidget *GtkAbout_LabelGreets; + GtkWidget *hbuttonbox1; + GtkWidget *GtkButton_Ok; + + AboutDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (AboutDlg), "AboutDlg", AboutDlg); + gtk_container_set_border_width (GTK_CONTAINER (AboutDlg), 10); + gtk_window_set_title (GTK_WINDOW (AboutDlg), _("Pcsx About")); + gtk_window_set_position (GTK_WINDOW (AboutDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (AboutDlg), FALSE, FALSE, FALSE); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (AboutDlg), vbox2); + + packer1 = gtk_packer_new (); + gtk_widget_ref (packer1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "packer1", packer1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (packer1); + gtk_box_pack_start (GTK_BOX (vbox2), packer1, FALSE, FALSE, 0); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox4); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox4", vbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox4); + gtk_box_pack_start (GTK_BOX (hbox1), vbox4, TRUE, TRUE, 0); + + GtkAbout_LabelVersion = gtk_label_new (_("PCSX2\r\r\r\nVersion x.x")); + gtk_widget_ref (GtkAbout_LabelVersion); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelVersion", GtkAbout_LabelVersion, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelVersion); + gtk_box_pack_start (GTK_BOX (vbox4), GtkAbout_LabelVersion, FALSE, FALSE, 0); + + frame1 = gtk_frame_new (NULL); + gtk_widget_ref (frame1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "frame1", frame1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox4), frame1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame1), 5); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox6); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox6", vbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (frame1), vbox6); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 5); + + GtkAbout_LabelAuthors = gtk_label_new (_("written by...")); + gtk_widget_ref (GtkAbout_LabelAuthors); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelAuthors", GtkAbout_LabelAuthors, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelAuthors); + gtk_box_pack_start (GTK_BOX (vbox6), GtkAbout_LabelAuthors, FALSE, FALSE, 0); + + pixmap1 = create_pixmap (AboutDlg, "pcsxAbout.xpm"); + gtk_widget_ref (pixmap1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "pixmap1", pixmap1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (pixmap1); + gtk_box_pack_start (GTK_BOX (hbox1), pixmap1, TRUE, TRUE, 0); + + frame2 = gtk_frame_new (NULL); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox2), frame2, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame2), 5); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox5); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox5", vbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox5); + gtk_container_add (GTK_CONTAINER (frame2), vbox5); + gtk_container_set_border_width (GTK_CONTAINER (vbox5), 5); + + GtkAbout_LabelGreets = gtk_label_new (_("greets to...")); + gtk_widget_ref (GtkAbout_LabelGreets); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelGreets", GtkAbout_LabelGreets, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelGreets); + gtk_box_pack_start (GTK_BOX (vbox5), GtkAbout_LabelGreets, FALSE, FALSE, 0); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox1, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnHelpAbout_Ok), + NULL); + + return AboutDlg; +} + +GtkWidget* +create_ConfDlg (void) +{ + GtkWidget *ConfDlg; + GtkWidget *vbox12; + GtkWidget *table2; + GtkWidget *GtkCombo_Pad1; + GtkWidget *combo_entry4; + GtkWidget *GtkCombo_Pad2; + GtkWidget *combo_entry5; + GtkWidget *hbuttonbox6; + GtkWidget *GtkButton_PAD2configure; + GtkWidget *GtkButton_PAD2test; + GtkWidget *GtkButton_PAD2about; + GtkWidget *hbuttonbox7; + GtkWidget *GtkButton_PAD1configure; + GtkWidget *GtkButton_PAD1test; + GtkWidget *GtkButton_PAD1about; + GtkWidget *hbuttonbox8; + GtkWidget *GtkButton_GSconfigure; + GtkWidget *GtkButton_GStest; + GtkWidget *GtkButton_GSabout; + GtkWidget *GtkLabel_Graphics; + GtkWidget *GtkLabel_FirstController; + GtkWidget *GtkLabel_SecondController; + GtkWidget *GtkCombo_Gs; + GtkWidget *combo_entry2; + GtkWidget *GtkLabel_Sound; + GtkWidget *GtkCombo_Spu2; + GtkWidget *entry1; + GtkWidget *hbuttonbox12; + GtkWidget *GtkButton_SPU2configure; + GtkWidget *GtkButton_SPU2test; + GtkWidget *GtkButton_SPU2about; + GtkWidget *GtkCombo_Dev9; + GtkWidget *entry3; + GtkWidget *hbuttonbox21; + GtkWidget *GtkButton_DEV9configure; + GtkWidget *GtkButton_DEV9test; + GtkWidget *GtkButton_DEV9about; + GtkWidget *label23; + GtkWidget *GtkLabel_Cdvdrom; + GtkWidget *GtkCombo_Cdvd; + GtkWidget *entry2; + GtkWidget *hbuttonbox13; + GtkWidget *GtkButton_CDVDconfigure; + GtkWidget *GtkButton_CDVDtest; + GtkWidget *GtkButton_CDVDabout; + GtkWidget *label29; + GtkWidget *GtkCombo_Usb; + GtkWidget *entry4; + GtkWidget *hbuttonbox23; + GtkWidget *GtkButton_USBconfigure; + GtkWidget *GtkButton_USBtest; + GtkWidget *GtkButton_USBabout; + GtkWidget *GtkCombo_Bios; + GtkWidget *combo_entry7; + GtkWidget *GtkCombo_FW; + GtkWidget *entry5; + GtkWidget *hbuttonbox24; + GtkWidget *GtkButton_FWconfigure; + GtkWidget *GtkButton_FWtest; + GtkWidget *GtkButton_FWabout; + GtkWidget *label30; + GtkWidget *GtkLabel_Bios; + GtkWidget *hbox5; + GtkWidget *hbuttonbox11; + GtkWidget *GtkButton_SelectPluginsDir; + GtkWidget *GtkButton_SelectBiosDir; + GtkWidget *hbuttonbox10; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + ConfDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (ConfDlg), "ConfDlg", ConfDlg); + gtk_container_set_border_width (GTK_CONTAINER (ConfDlg), 10); + gtk_window_set_title (GTK_WINDOW (ConfDlg), _("Conf")); + gtk_window_set_position (GTK_WINDOW (ConfDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (ConfDlg), FALSE, FALSE, FALSE); + + vbox12 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox12); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "vbox12", vbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox12); + gtk_container_add (GTK_CONTAINER (ConfDlg), vbox12); + + table2 = gtk_table_new (14, 2, FALSE); + gtk_widget_ref (table2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "table2", table2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table2); + gtk_box_pack_start (GTK_BOX (vbox12), table2, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table2), 15); + + GtkCombo_Pad1 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Pad1); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Pad1", GtkCombo_Pad1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Pad1); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad1, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry4 = GTK_COMBO (GtkCombo_Pad1)->entry; + gtk_widget_ref (combo_entry4); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry4", combo_entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry4); + + GtkCombo_Pad2 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Pad2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Pad2", GtkCombo_Pad2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Pad2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad2, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry5 = GTK_COMBO (GtkCombo_Pad2)->entry; + gtk_widget_ref (combo_entry5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry5", combo_entry5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry5); + + hbuttonbox6 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox6); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox6", hbuttonbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox6); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox6, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox6), 0); + + GtkButton_PAD2configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_PAD2configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2configure", GtkButton_PAD2configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2configure, GTK_CAN_DEFAULT); + + GtkButton_PAD2test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_PAD2test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2test", GtkButton_PAD2test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2test, GTK_CAN_DEFAULT); + + GtkButton_PAD2about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_PAD2about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2about", GtkButton_PAD2about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2about, GTK_CAN_DEFAULT); + + hbuttonbox7 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox7); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox7", hbuttonbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox7); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox7, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox7), 0); + + GtkButton_PAD1configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_PAD1configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1configure", GtkButton_PAD1configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1configure, GTK_CAN_DEFAULT); + + GtkButton_PAD1test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_PAD1test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1test", GtkButton_PAD1test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1test); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1test, GTK_CAN_DEFAULT); + + GtkButton_PAD1about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_PAD1about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1about", GtkButton_PAD1about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1about); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1about, GTK_CAN_DEFAULT); + + hbuttonbox8 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox8); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox8", hbuttonbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox8); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox8, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox8), 0); + + GtkButton_GSconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_GSconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GSconfigure", GtkButton_GSconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GSconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_GSconfigure, GTK_CAN_DEFAULT); + + GtkButton_GStest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_GStest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GStest", GtkButton_GStest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GStest); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GStest); + GTK_WIDGET_SET_FLAGS (GtkButton_GStest, GTK_CAN_DEFAULT); + + GtkButton_GSabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_GSabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GSabout", GtkButton_GSabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GSabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSabout); + GTK_WIDGET_SET_FLAGS (GtkButton_GSabout, GTK_CAN_DEFAULT); + + GtkLabel_Graphics = gtk_label_new (_("Graphics")); + gtk_widget_ref (GtkLabel_Graphics); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Graphics", GtkLabel_Graphics, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Graphics); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Graphics, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Graphics), 0, 0.5); + + GtkLabel_FirstController = gtk_label_new (_("First Controller")); + gtk_widget_ref (GtkLabel_FirstController); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_FirstController", GtkLabel_FirstController, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_FirstController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_FirstController, 0, 1, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_FirstController), 0, 0.5); + + GtkLabel_SecondController = gtk_label_new (_("Second Controller")); + gtk_widget_ref (GtkLabel_SecondController); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_SecondController", GtkLabel_SecondController, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_SecondController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_SecondController, 1, 2, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_SecondController), 0, 0.5); + + GtkCombo_Gs = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Gs); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Gs", GtkCombo_Gs, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Gs); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Gs, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry2 = GTK_COMBO (GtkCombo_Gs)->entry; + gtk_widget_ref (combo_entry2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry2", combo_entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry2); + + GtkLabel_Sound = gtk_label_new (_("Sound")); + gtk_widget_ref (GtkLabel_Sound); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Sound", GtkLabel_Sound, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Sound); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Sound, 1, 2, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Sound), 0, 0.5); + + GtkCombo_Spu2 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Spu2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Spu2", GtkCombo_Spu2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Spu2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Spu2, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry1 = GTK_COMBO (GtkCombo_Spu2)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox12 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox12); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox12", hbuttonbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox12); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox12, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox12), 0); + + GtkButton_SPU2configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_SPU2configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2configure", GtkButton_SPU2configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2configure, GTK_CAN_DEFAULT); + + GtkButton_SPU2test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_SPU2test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2test", GtkButton_SPU2test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2test); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2test, GTK_CAN_DEFAULT); + + GtkButton_SPU2about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_SPU2about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2about", GtkButton_SPU2about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2about); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2about, GTK_CAN_DEFAULT); + + GtkCombo_Dev9 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Dev9); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Dev9", GtkCombo_Dev9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Dev9); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Dev9, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry3 = GTK_COMBO (GtkCombo_Dev9)->entry; + gtk_widget_ref (entry3); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry3", entry3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry3); + + hbuttonbox21 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox21); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox21", hbuttonbox21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox21); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox21, 0, 1, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox21), 0); + + GtkButton_DEV9configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_DEV9configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9configure", GtkButton_DEV9configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9configure); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9configure, GTK_CAN_DEFAULT); + + GtkButton_DEV9test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_DEV9test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9test", GtkButton_DEV9test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9test); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9test); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9test, GTK_CAN_DEFAULT); + + GtkButton_DEV9about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_DEV9about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9about", GtkButton_DEV9about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9about); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9about); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9about, GTK_CAN_DEFAULT); + + label23 = gtk_label_new (_("Dev9")); + gtk_widget_ref (label23); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label23", label23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label23); + gtk_table_attach (GTK_TABLE (table2), label23, 0, 1, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label23), 0, 0.5); + + GtkLabel_Cdvdrom = gtk_label_new (_("Cdvdrom")); + gtk_widget_ref (GtkLabel_Cdvdrom); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Cdvdrom", GtkLabel_Cdvdrom, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Cdvdrom); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Cdvdrom, 1, 2, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Cdvdrom), 0, 0.5); + + GtkCombo_Cdvd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Cdvd); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Cdvd", GtkCombo_Cdvd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Cdvd); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Cdvd, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry2 = GTK_COMBO (GtkCombo_Cdvd)->entry; + gtk_widget_ref (entry2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry2", entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry2); + + hbuttonbox13 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox13); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox13", hbuttonbox13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox13); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox13, 1, 2, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox13), 0); + + GtkButton_CDVDconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_CDVDconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDconfigure", GtkButton_CDVDconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDconfigure, GTK_CAN_DEFAULT); + + GtkButton_CDVDtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_CDVDtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDtest", GtkButton_CDVDtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDtest); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDtest, GTK_CAN_DEFAULT); + + GtkButton_CDVDabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_CDVDabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDabout", GtkButton_CDVDabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDabout); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDabout, GTK_CAN_DEFAULT); + + label29 = gtk_label_new (_("Usb")); + gtk_widget_ref (label29); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label29", label29, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label29); + gtk_table_attach (GTK_TABLE (table2), label29, 0, 1, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label29), 0, 0.5); + + GtkCombo_Usb = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Usb); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Usb", GtkCombo_Usb, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Usb); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Usb, 0, 1, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry4 = GTK_COMBO (GtkCombo_Usb)->entry; + gtk_widget_ref (entry4); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry4", entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry4); + + hbuttonbox23 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox23); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox23", hbuttonbox23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox23); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox23, 0, 1, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox23), 0); + + GtkButton_USBconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_USBconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBconfigure", GtkButton_USBconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_USBconfigure, GTK_CAN_DEFAULT); + + GtkButton_USBtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_USBtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBtest", GtkButton_USBtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBtest); + GTK_WIDGET_SET_FLAGS (GtkButton_USBtest, GTK_CAN_DEFAULT); + + GtkButton_USBabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_USBabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBabout", GtkButton_USBabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBabout); + GTK_WIDGET_SET_FLAGS (GtkButton_USBabout, GTK_CAN_DEFAULT); + + GtkCombo_Bios = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Bios); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Bios", GtkCombo_Bios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Bios, 1, 2, 13, 14, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry7 = GTK_COMBO (GtkCombo_Bios)->entry; + gtk_widget_ref (combo_entry7); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry7", combo_entry7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry7); + + GtkCombo_FW = gtk_combo_new (); + gtk_widget_ref (GtkCombo_FW); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_FW", GtkCombo_FW, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_FW); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_FW, 1, 2, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry5 = GTK_COMBO (GtkCombo_FW)->entry; + gtk_widget_ref (entry5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry5", entry5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry5); + + hbuttonbox24 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox24); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox24", hbuttonbox24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox24); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox24, 1, 2, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox24), 0); + + GtkButton_FWconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_FWconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWconfigure", GtkButton_FWconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_FWconfigure, GTK_CAN_DEFAULT); + + GtkButton_FWtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_FWtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWtest", GtkButton_FWtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWtest); + GTK_WIDGET_SET_FLAGS (GtkButton_FWtest, GTK_CAN_DEFAULT); + + GtkButton_FWabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_FWabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWabout", GtkButton_FWabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWabout); + GTK_WIDGET_SET_FLAGS (GtkButton_FWabout, GTK_CAN_DEFAULT); + + label30 = gtk_label_new (_("FW")); + gtk_widget_ref (label30); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label30", label30, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label30); + gtk_table_attach (GTK_TABLE (table2), label30, 1, 2, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label30), 0, 0.5); + + GtkLabel_Bios = gtk_label_new (_("Bios")); + gtk_widget_ref (GtkLabel_Bios); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Bios", GtkLabel_Bios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Bios, 1, 2, 12, 13, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Bios), 0, 0.5); + + hbox5 = gtk_hbox_new (FALSE, 14); + gtk_widget_ref (hbox5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbox5", hbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox5); + gtk_box_pack_start (GTK_BOX (vbox12), hbox5, TRUE, TRUE, 0); + + hbuttonbox11 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox11); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox11", hbuttonbox11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox11); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox11, FALSE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox11), GTK_BUTTONBOX_START); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox11), 0); + + GtkButton_SelectPluginsDir = gtk_button_new_with_label (_("Select Plugins Dir")); + gtk_widget_ref (GtkButton_SelectPluginsDir); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SelectPluginsDir", GtkButton_SelectPluginsDir, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SelectPluginsDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectPluginsDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectPluginsDir, GTK_CAN_DEFAULT); + + GtkButton_SelectBiosDir = gtk_button_new_with_label (_("Select Bios Dir")); + gtk_widget_ref (GtkButton_SelectBiosDir); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SelectBiosDir", GtkButton_SelectBiosDir, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SelectBiosDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectBiosDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectBiosDir, GTK_CAN_DEFAULT); + + hbuttonbox10 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox10); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox10", hbuttonbox10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox10); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox10, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox10), 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GSconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GStest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GSabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SelectPluginsDir), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_PluginsPath), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SelectBiosDir), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_BiosPath), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Cancel), + NULL); + + return ConfDlg; +} + +GtkWidget* +create_CpuDlg (void) +{ + GtkWidget *CpuDlg; + GtkWidget *vbox8; + GtkWidget *hbox20; + GtkWidget *GtkFrame_Options; + GtkWidget *vbox15; + GtkWidget *GtkCheckButton_PsxOut; + GtkWidget *GtkCheckButton_Patches; + GtkWidget *frame6; + GtkWidget *vbox26; + GtkWidget *GtkCheckButton_Cpu; + GtkWidget *GtkCheckButton_RegCaching; + GtkWidget *GtkCheckButton_VUrec; + GtkWidget *hbuttonbox3; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + CpuDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (CpuDlg), "CpuDlg", CpuDlg); + gtk_container_set_border_width (GTK_CONTAINER (CpuDlg), 5); + gtk_window_set_title (GTK_WINDOW (CpuDlg), _("Cpu")); + gtk_window_set_position (GTK_WINDOW (CpuDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (CpuDlg), FALSE, FALSE, FALSE); + + vbox8 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox8); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox8", vbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (CpuDlg), vbox8); + + hbox20 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox20); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "hbox20", hbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox20); + gtk_box_pack_start (GTK_BOX (vbox8), hbox20, TRUE, TRUE, 0); + + GtkFrame_Options = gtk_frame_new (_("Options")); + gtk_widget_ref (GtkFrame_Options); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkFrame_Options", GtkFrame_Options, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkFrame_Options); + gtk_box_pack_start (GTK_BOX (hbox20), GtkFrame_Options, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (GtkFrame_Options), 5); + + vbox15 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox15); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox15", vbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox15); + gtk_container_add (GTK_CONTAINER (GtkFrame_Options), vbox15); + gtk_container_set_border_width (GTK_CONTAINER (vbox15), 5); + + GtkCheckButton_PsxOut = gtk_check_button_new_with_label (_("Enable Console Output")); + gtk_widget_ref (GtkCheckButton_PsxOut); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_PsxOut", GtkCheckButton_PsxOut, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_PsxOut); + gtk_box_pack_start (GTK_BOX (vbox15), GtkCheckButton_PsxOut, FALSE, FALSE, 0); + + GtkCheckButton_Patches = gtk_check_button_new_with_label (_("Enable Patches")); + gtk_widget_ref (GtkCheckButton_Patches); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_Patches", GtkCheckButton_Patches, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Patches); + gtk_box_pack_start (GTK_BOX (vbox15), GtkCheckButton_Patches, FALSE, FALSE, 0); + + frame6 = gtk_frame_new (_("Recompiler Options")); + gtk_widget_ref (frame6); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "frame6", frame6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame6); + gtk_box_pack_start (GTK_BOX (vbox8), frame6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame6), 5); + + vbox26 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox26); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox26", vbox26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox26); + gtk_container_add (GTK_CONTAINER (frame6), vbox26); + gtk_container_set_border_width (GTK_CONTAINER (vbox26), 5); + + GtkCheckButton_Cpu = gtk_check_button_new_with_label (_("Disable Recompiler")); + gtk_widget_ref (GtkCheckButton_Cpu); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_Cpu", GtkCheckButton_Cpu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Cpu); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_Cpu, FALSE, FALSE, 0); + + GtkCheckButton_RegCaching = gtk_check_button_new_with_label (_("Enable Reg Caching")); + gtk_widget_ref (GtkCheckButton_RegCaching); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_RegCaching", GtkCheckButton_RegCaching, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_RegCaching); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_RegCaching, FALSE, FALSE, 0); + + GtkCheckButton_VUrec = gtk_check_button_new_with_label (_("Disable VUs recompilation")); + gtk_widget_ref (GtkCheckButton_VUrec); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_VUrec", GtkCheckButton_VUrec, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_VUrec); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_VUrec, FALSE, FALSE, 0); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "hbuttonbox3", hbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox8), hbuttonbox3, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnCpu_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnCpu_Cancel), + NULL); + + return CpuDlg; +} + +GtkWidget* +create_DebugWnd (void) +{ + GtkWidget *DebugWnd; + GtkWidget *vbox16; + GtkWidget *hbox16; + GSList *Debug_group = NULL; + GtkWidget *GtkRadioButton_EE; + GtkWidget *GtkRadioButton_IOP; + GtkWidget *hbox6; + GtkWidget *hbox7; + GtkWidget *scrolledwindow1; + GtkWidget *viewport1; + GtkWidget *GtkList_DisView; + GtkWidget *GtkVScrollbar_VList; + GtkWidget *vbox22; + GtkWidget *vbuttonbox2; + GtkWidget *button52; + GtkWidget *button53; + GtkWidget *button65; + GtkWidget *button64; + GtkWidget *vbuttonbox3; + GtkWidget *button58; + GtkWidget *button59; + GtkWidget *button60; + GtkWidget *button61; + GtkWidget *vbuttonbox1; + GtkWidget *button39; + GtkWidget *button40; + GtkWidget *button41; + GtkWidget *vbuttonbox4; + GtkWidget *button68; + GtkWidget *button69; + GtkWidget *button70; + + DebugWnd = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (DebugWnd), "DebugWnd", DebugWnd); + gtk_container_set_border_width (GTK_CONTAINER (DebugWnd), 5); + gtk_window_set_title (GTK_WINDOW (DebugWnd), _("PCSX2 Debugger")); + gtk_window_set_position (GTK_WINDOW (DebugWnd), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DebugWnd), FALSE, FALSE, FALSE); + + vbox16 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox16); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbox16", vbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox16); + gtk_container_add (GTK_CONTAINER (DebugWnd), vbox16); + gtk_container_set_border_width (GTK_CONTAINER (vbox16), 5); + + hbox16 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox16); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox16", hbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox16); + gtk_box_pack_start (GTK_BOX (vbox16), hbox16, TRUE, TRUE, 0); + + GtkRadioButton_EE = gtk_radio_button_new_with_label (Debug_group, _("EE Debug Mode")); + Debug_group = gtk_radio_button_group (GTK_RADIO_BUTTON (GtkRadioButton_EE)); + gtk_widget_ref (GtkRadioButton_EE); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkRadioButton_EE", GtkRadioButton_EE, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkRadioButton_EE); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_EE, FALSE, FALSE, 0); + + GtkRadioButton_IOP = gtk_radio_button_new_with_label (Debug_group, _("IOP Debug Mode")); + Debug_group = gtk_radio_button_group (GTK_RADIO_BUTTON (GtkRadioButton_IOP)); + gtk_widget_ref (GtkRadioButton_IOP); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkRadioButton_IOP", GtkRadioButton_IOP, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkRadioButton_IOP); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_IOP, FALSE, FALSE, 0); + + hbox6 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox6); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox6", hbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox6); + gtk_box_pack_start (GTK_BOX (vbox16), hbox6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox6), 5); + + hbox7 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox7); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox7", hbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox7); + gtk_box_pack_start (GTK_BOX (hbox6), hbox7, TRUE, TRUE, 0); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_ref (scrolledwindow1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "scrolledwindow1", scrolledwindow1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (scrolledwindow1); + gtk_box_pack_start (GTK_BOX (hbox7), scrolledwindow1, TRUE, TRUE, 0); + gtk_widget_set_usize (scrolledwindow1, 320, -2); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER); + + viewport1 = gtk_viewport_new (NULL, NULL); + gtk_widget_ref (viewport1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "viewport1", viewport1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (viewport1); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); + + GtkList_DisView = gtk_list_new (); + gtk_widget_ref (GtkList_DisView); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkList_DisView", GtkList_DisView, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkList_DisView); + gtk_container_add (GTK_CONTAINER (viewport1), GtkList_DisView); + + GtkVScrollbar_VList = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 412, 1, 20, 2))); + gtk_widget_ref (GtkVScrollbar_VList); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkVScrollbar_VList", GtkVScrollbar_VList, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkVScrollbar_VList); + gtk_box_pack_start (GTK_BOX (hbox7), GtkVScrollbar_VList, TRUE, TRUE, 0); + + vbox22 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox22); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbox22", vbox22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox22); + gtk_box_pack_start (GTK_BOX (hbox6), vbox22, TRUE, TRUE, 0); + + vbuttonbox2 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox2", vbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox2, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox2), 0); + + button52 = gtk_button_new_with_label (_("Step")); + gtk_widget_ref (button52); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button52", button52, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button52); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button52); + GTK_WIDGET_SET_FLAGS (button52, GTK_CAN_DEFAULT); + + button53 = gtk_button_new_with_label (_("Skip")); + gtk_widget_ref (button53); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button53", button53, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button53); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button53); + GTK_WIDGET_SET_FLAGS (button53, GTK_CAN_DEFAULT); + + button65 = gtk_button_new_with_label (_("Go")); + gtk_widget_ref (button65); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button65", button65, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button65); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button65); + GTK_WIDGET_SET_FLAGS (button65, GTK_CAN_DEFAULT); + + button64 = gtk_button_new_with_label (_("Log On/Off")); + gtk_widget_ref (button64); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button64", button64, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button64); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button64); + GTK_WIDGET_SET_FLAGS (button64, GTK_CAN_DEFAULT); + + vbuttonbox3 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox3", vbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox3, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox3), 0); + + button58 = gtk_button_new_with_label (_("Set PC")); + gtk_widget_ref (button58); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button58", button58, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button58); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button58); + GTK_WIDGET_SET_FLAGS (button58, GTK_CAN_DEFAULT); + + button59 = gtk_button_new_with_label (_("Set BP Addr")); + gtk_widget_ref (button59); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button59", button59, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button59); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button59); + GTK_WIDGET_SET_FLAGS (button59, GTK_CAN_DEFAULT); + + button60 = gtk_button_new_with_label (_("Set BP Count")); + gtk_widget_ref (button60); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button60", button60, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button60); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button60); + GTK_WIDGET_SET_FLAGS (button60, GTK_CAN_DEFAULT); + + button61 = gtk_button_new_with_label (_("Clear BPs")); + gtk_widget_ref (button61); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button61", button61, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button61); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button61); + GTK_WIDGET_SET_FLAGS (button61, GTK_CAN_DEFAULT); + + vbuttonbox1 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox1", vbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox1, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox1), 0); + + button39 = gtk_button_new_with_label (_("Dump code")); + gtk_widget_ref (button39); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button39", button39, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button39); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button39); + GTK_WIDGET_SET_FLAGS (button39, GTK_CAN_DEFAULT); + + button40 = gtk_button_new_with_label (_("Raw Dump")); + gtk_widget_ref (button40); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button40", button40, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button40); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button40); + GTK_WIDGET_SET_FLAGS (button40, GTK_CAN_DEFAULT); + + button41 = gtk_button_new_with_label (_("Close")); + gtk_widget_ref (button41); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button41", button41, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button41); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button41); + GTK_WIDGET_SET_FLAGS (button41, GTK_CAN_DEFAULT); + + vbuttonbox4 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox4); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox4", vbuttonbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox4); + gtk_box_pack_start (GTK_BOX (hbox6), vbuttonbox4, TRUE, TRUE, 0); + + button68 = gtk_button_new_with_label (_("memWrite32")); + gtk_widget_ref (button68); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button68", button68, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button68); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button68); + GTK_WIDGET_SET_FLAGS (button68, GTK_CAN_DEFAULT); + + button69 = gtk_button_new_with_label (_("button69")); + gtk_widget_ref (button69); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button69", button69, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button69); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button69); + GTK_WIDGET_SET_FLAGS (button69, GTK_CAN_DEFAULT); + + button70 = gtk_button_new_with_label (_("button70")); + gtk_widget_ref (button70); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button70", button70, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button70); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button70); + GTK_WIDGET_SET_FLAGS (button70, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkRadioButton_EE), "toggled", + GTK_SIGNAL_FUNC (OnDebug_EEMode), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkRadioButton_IOP), "toggled", + GTK_SIGNAL_FUNC (OnDebug_IOPMode), + NULL); + gtk_signal_connect (GTK_OBJECT (button52), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Step), + NULL); + gtk_signal_connect (GTK_OBJECT (button53), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Skip), + NULL); + gtk_signal_connect (GTK_OBJECT (button65), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Go), + NULL); + gtk_signal_connect (GTK_OBJECT (button64), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Log), + NULL); + gtk_signal_connect (GTK_OBJECT (button58), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetPC), + NULL); + gtk_signal_connect (GTK_OBJECT (button59), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetBPA), + NULL); + gtk_signal_connect (GTK_OBJECT (button60), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetBPC), + NULL); + gtk_signal_connect (GTK_OBJECT (button61), "clicked", + GTK_SIGNAL_FUNC (OnDebug_ClearBPs), + NULL); + gtk_signal_connect (GTK_OBJECT (button39), "clicked", + GTK_SIGNAL_FUNC (OnDebug_DumpCode), + NULL); + gtk_signal_connect (GTK_OBJECT (button40), "clicked", + GTK_SIGNAL_FUNC (OnDebug_RawDump), + NULL); + gtk_signal_connect (GTK_OBJECT (button41), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Close), + NULL); + gtk_signal_connect (GTK_OBJECT (button68), "clicked", + GTK_SIGNAL_FUNC (OnDebug_memWrite32), + NULL); + + return DebugWnd; +} + +GtkWidget* +create_SetPCDlg (void) +{ + GtkWidget *SetPCDlg; + GtkWidget *vbox17; + GtkWidget *label9; + GtkWidget *hbox8; + GtkWidget *label10; + GtkWidget *GtkEntry_dPC; + GtkWidget *hbuttonbox14; + GtkWidget *button42; + GtkWidget *button43; + + SetPCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetPCDlg), "SetPCDlg", SetPCDlg); + gtk_container_set_border_width (GTK_CONTAINER (SetPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetPCDlg), _("SetPCDlg")); + gtk_window_set_position (GTK_WINDOW (SetPCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetPCDlg), FALSE, FALSE, FALSE); + + vbox17 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox17); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "vbox17", vbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox17); + gtk_container_add (GTK_CONTAINER (SetPCDlg), vbox17); + gtk_container_set_border_width (GTK_CONTAINER (vbox17), 5); + + label9 = gtk_label_new (_("Set New PC Address (in Hex):")); + gtk_widget_ref (label9); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "label9", label9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label9); + gtk_box_pack_start (GTK_BOX (vbox17), label9, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label9), 0.1, 0.5); + + hbox8 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox8); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "hbox8", hbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox8); + gtk_box_pack_start (GTK_BOX (vbox17), hbox8, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox8), 5); + + label10 = gtk_label_new (_("0x")); + gtk_widget_ref (label10); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "label10", label10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label10); + gtk_box_pack_start (GTK_BOX (hbox8), label10, FALSE, FALSE, 0); + + GtkEntry_dPC = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_dPC); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "GtkEntry_dPC", GtkEntry_dPC, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_dPC); + gtk_box_pack_start (GTK_BOX (hbox8), GtkEntry_dPC, TRUE, TRUE, 0); + + hbuttonbox14 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox14); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "hbuttonbox14", hbuttonbox14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox14); + gtk_box_pack_start (GTK_BOX (vbox17), hbuttonbox14, TRUE, TRUE, 0); + + button42 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button42); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "button42", button42, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button42); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button42); + GTK_WIDGET_SET_FLAGS (button42, GTK_CAN_DEFAULT); + + button43 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button43); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "button43", button43, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button43); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button43); + GTK_WIDGET_SET_FLAGS (button43, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button42), "clicked", + GTK_SIGNAL_FUNC (OnSetPC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button43), "clicked", + GTK_SIGNAL_FUNC (OnSetPC_Cancel), + NULL); + + return SetPCDlg; +} + +GtkWidget* +create_SetBPADlg (void) +{ + GtkWidget *SetBPADlg; + GtkWidget *vbox18; + GtkWidget *label11; + GtkWidget *hbox9; + GtkWidget *label12; + GtkWidget *GtkEntry_BPA; + GtkWidget *hbuttonbox15; + GtkWidget *button44; + GtkWidget *button45; + + SetBPADlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetBPADlg), "SetBPADlg", SetBPADlg); + gtk_container_set_border_width (GTK_CONTAINER (SetBPADlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPADlg), _("SetBreakPoint Addr")); + gtk_window_set_position (GTK_WINDOW (SetBPADlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetBPADlg), FALSE, FALSE, FALSE); + + vbox18 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox18); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "vbox18", vbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox18); + gtk_container_add (GTK_CONTAINER (SetBPADlg), vbox18); + gtk_container_set_border_width (GTK_CONTAINER (vbox18), 5); + + label11 = gtk_label_new (_("Set New BP Address (in Hex):")); + gtk_widget_ref (label11); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "label11", label11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label11); + gtk_box_pack_start (GTK_BOX (vbox18), label11, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label11), 0.1, 0.5); + + hbox9 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox9); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "hbox9", hbox9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox9); + gtk_box_pack_start (GTK_BOX (vbox18), hbox9, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox9), 5); + + label12 = gtk_label_new (_("0x")); + gtk_widget_ref (label12); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "label12", label12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label12); + gtk_box_pack_start (GTK_BOX (hbox9), label12, FALSE, FALSE, 0); + + GtkEntry_BPA = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_BPA); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "GtkEntry_BPA", GtkEntry_BPA, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_BPA); + gtk_box_pack_start (GTK_BOX (hbox9), GtkEntry_BPA, TRUE, TRUE, 0); + + hbuttonbox15 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox15); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "hbuttonbox15", hbuttonbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox15); + gtk_box_pack_start (GTK_BOX (vbox18), hbuttonbox15, TRUE, TRUE, 0); + + button44 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button44); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "button44", button44, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button44); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button44); + GTK_WIDGET_SET_FLAGS (button44, GTK_CAN_DEFAULT); + + button45 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button45); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "button45", button45, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button45); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button45); + GTK_WIDGET_SET_FLAGS (button45, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button44), "clicked", + GTK_SIGNAL_FUNC (OnSetBPA_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button45), "clicked", + GTK_SIGNAL_FUNC (OnSetBPA_Cancel), + NULL); + + return SetBPADlg; +} + +GtkWidget* +create_SetBPCDlg (void) +{ + GtkWidget *SetBPCDlg; + GtkWidget *vbox19; + GtkWidget *label13; + GtkWidget *hbox10; + GtkWidget *label14; + GtkWidget *GtkEntry_BPC; + GtkWidget *hbuttonbox16; + GtkWidget *button46; + GtkWidget *button47; + + SetBPCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetBPCDlg), "SetBPCDlg", SetBPCDlg); + gtk_container_set_border_width (GTK_CONTAINER (SetBPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPCDlg), _("SetBreakPoint Addr")); + gtk_window_set_position (GTK_WINDOW (SetBPCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetBPCDlg), FALSE, FALSE, FALSE); + + vbox19 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox19); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "vbox19", vbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox19); + gtk_container_add (GTK_CONTAINER (SetBPCDlg), vbox19); + gtk_container_set_border_width (GTK_CONTAINER (vbox19), 5); + + label13 = gtk_label_new (_("Set New BP Count (in Hex):")); + gtk_widget_ref (label13); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "label13", label13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label13); + gtk_box_pack_start (GTK_BOX (vbox19), label13, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label13), 0.1, 0.5); + + hbox10 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox10); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "hbox10", hbox10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox10); + gtk_box_pack_start (GTK_BOX (vbox19), hbox10, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox10), 5); + + label14 = gtk_label_new (_("0x")); + gtk_widget_ref (label14); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "label14", label14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label14); + gtk_box_pack_start (GTK_BOX (hbox10), label14, FALSE, FALSE, 0); + + GtkEntry_BPC = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_BPC); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "GtkEntry_BPC", GtkEntry_BPC, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_BPC); + gtk_box_pack_start (GTK_BOX (hbox10), GtkEntry_BPC, TRUE, TRUE, 0); + + hbuttonbox16 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox16); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "hbuttonbox16", hbuttonbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox16); + gtk_box_pack_start (GTK_BOX (vbox19), hbuttonbox16, TRUE, TRUE, 0); + + button46 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button46); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "button46", button46, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button46); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button46); + GTK_WIDGET_SET_FLAGS (button46, GTK_CAN_DEFAULT); + + button47 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button47); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "button47", button47, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button47); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button47); + GTK_WIDGET_SET_FLAGS (button47, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button46), "clicked", + GTK_SIGNAL_FUNC (OnSetBPC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button47), "clicked", + GTK_SIGNAL_FUNC (OnSetBPC_Cancel), + NULL); + + return SetBPCDlg; +} + +GtkWidget* +create_DumpCDlg (void) +{ + GtkWidget *DumpCDlg; + GtkWidget *vbox20; + GtkWidget *label15; + GtkWidget *hbox11; + GtkWidget *label16; + GtkWidget *GtkEntry_DumpCF; + GtkWidget *hbox12; + GtkWidget *label17; + GtkWidget *GtkEntry_DumpCT; + GtkWidget *label21; + GtkWidget *hbuttonbox17; + GtkWidget *button48; + GtkWidget *button49; + + DumpCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (DumpCDlg), "DumpCDlg", DumpCDlg); + gtk_container_set_border_width (GTK_CONTAINER (DumpCDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpCDlg), _("Dump code")); + gtk_window_set_position (GTK_WINDOW (DumpCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DumpCDlg), FALSE, FALSE, FALSE); + + vbox20 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox20); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "vbox20", vbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox20); + gtk_container_add (GTK_CONTAINER (DumpCDlg), vbox20); + gtk_container_set_border_width (GTK_CONTAINER (vbox20), 5); + + label15 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_ref (label15); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label15", label15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label15); + gtk_box_pack_start (GTK_BOX (vbox20), label15, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label15), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label15), 0.1, 0.5); + + hbox11 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox11); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbox11", hbox11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox11); + gtk_box_pack_start (GTK_BOX (vbox20), hbox11, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox11), 5); + + label16 = gtk_label_new (_("From 0x")); + gtk_widget_ref (label16); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label16", label16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label16); + gtk_box_pack_start (GTK_BOX (hbox11), label16, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label16), TRUE); + + GtkEntry_DumpCF = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpCF); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "GtkEntry_DumpCF", GtkEntry_DumpCF, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpCF); + gtk_box_pack_start (GTK_BOX (hbox11), GtkEntry_DumpCF, TRUE, TRUE, 0); + + hbox12 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox12); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbox12", hbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox12); + gtk_box_pack_start (GTK_BOX (vbox20), hbox12, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox12), 5); + + label17 = gtk_label_new (_("To 0x")); + gtk_widget_ref (label17); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label17", label17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label17); + gtk_box_pack_start (GTK_BOX (hbox12), label17, FALSE, FALSE, 0); + gtk_widget_set_usize (label17, 45, -2); + + GtkEntry_DumpCT = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpCT); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "GtkEntry_DumpCT", GtkEntry_DumpCT, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpCT); + gtk_box_pack_start (GTK_BOX (hbox12), GtkEntry_DumpCT, TRUE, TRUE, 0); + + label21 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_ref (label21); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label21", label21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label21); + gtk_box_pack_start (GTK_BOX (vbox20), label21, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label21), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label21), 0.1, 0.5); + + hbuttonbox17 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox17); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbuttonbox17", hbuttonbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox17); + gtk_box_pack_start (GTK_BOX (vbox20), hbuttonbox17, TRUE, TRUE, 0); + + button48 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button48); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "button48", button48, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button48); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button48); + GTK_WIDGET_SET_FLAGS (button48, GTK_CAN_DEFAULT); + + button49 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button49); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "button49", button49, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button49); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button49); + GTK_WIDGET_SET_FLAGS (button49, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button48), "clicked", + GTK_SIGNAL_FUNC (OnDumpC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button49), "clicked", + GTK_SIGNAL_FUNC (OnDumpC_Cancel), + NULL); + + return DumpCDlg; +} + +GtkWidget* +create_DumpRDlg (void) +{ + GtkWidget *DumpRDlg; + GtkWidget *vbox21; + GtkWidget *label18; + GtkWidget *hbox13; + GtkWidget *label19; + GtkWidget *GtkEntry_DumpRF; + GtkWidget *hbox14; + GtkWidget *label20; + GtkWidget *GtkEntry_DumpRT; + GtkWidget *label22; + GtkWidget *hbuttonbox18; + GtkWidget *button50; + GtkWidget *button51; + + DumpRDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (DumpRDlg), "DumpRDlg", DumpRDlg); + gtk_container_set_border_width (GTK_CONTAINER (DumpRDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpRDlg), _("Raw Dump")); + gtk_window_set_position (GTK_WINDOW (DumpRDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DumpRDlg), FALSE, FALSE, FALSE); + + vbox21 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox21); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "vbox21", vbox21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox21); + gtk_container_add (GTK_CONTAINER (DumpRDlg), vbox21); + gtk_container_set_border_width (GTK_CONTAINER (vbox21), 5); + + label18 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_ref (label18); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label18", label18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label18); + gtk_box_pack_start (GTK_BOX (vbox21), label18, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label18), 0.1, 0.5); + + hbox13 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox13); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbox13", hbox13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox13); + gtk_box_pack_start (GTK_BOX (vbox21), hbox13, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox13), 5); + + label19 = gtk_label_new (_("From 0x")); + gtk_widget_ref (label19); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label19", label19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label19); + gtk_box_pack_start (GTK_BOX (hbox13), label19, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label19), TRUE); + + GtkEntry_DumpRF = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpRF); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "GtkEntry_DumpRF", GtkEntry_DumpRF, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpRF); + gtk_box_pack_start (GTK_BOX (hbox13), GtkEntry_DumpRF, TRUE, TRUE, 0); + + hbox14 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox14); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbox14", hbox14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox14); + gtk_box_pack_start (GTK_BOX (vbox21), hbox14, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox14), 5); + + label20 = gtk_label_new (_("To 0x")); + gtk_widget_ref (label20); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label20", label20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label20); + gtk_box_pack_start (GTK_BOX (hbox14), label20, FALSE, FALSE, 0); + gtk_widget_set_usize (label20, 45, -2); + gtk_label_set_justify (GTK_LABEL (label20), GTK_JUSTIFY_LEFT); + + GtkEntry_DumpRT = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpRT); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "GtkEntry_DumpRT", GtkEntry_DumpRT, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpRT); + gtk_box_pack_start (GTK_BOX (hbox14), GtkEntry_DumpRT, TRUE, TRUE, 0); + + label22 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_ref (label22); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label22", label22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label22); + gtk_box_pack_start (GTK_BOX (vbox21), label22, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label22), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label22), 0.1, 0.5); + + hbuttonbox18 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox18); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbuttonbox18", hbuttonbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox18); + gtk_box_pack_start (GTK_BOX (vbox21), hbuttonbox18, TRUE, TRUE, 0); + + button50 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button50); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "button50", button50, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button50); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button50); + GTK_WIDGET_SET_FLAGS (button50, GTK_CAN_DEFAULT); + + button51 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button51); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "button51", button51, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button51); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button51); + GTK_WIDGET_SET_FLAGS (button51, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button50), "clicked", + GTK_SIGNAL_FUNC (OnDumpR_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button51), "clicked", + GTK_SIGNAL_FUNC (OnDumpR_Cancel), + NULL); + + return DumpRDlg; +} + +GtkWidget* +create_Logging (void) +{ + GtkWidget *Logging; + GtkWidget *vbox23; + GtkWidget *hbox15; + GtkWidget *frame4; + GtkWidget *table3; + GtkWidget *Log0; + GtkWidget *Log1; + GtkWidget *Log2; + GtkWidget *Log3; + GtkWidget *Log4; + GtkWidget *Log5; + GtkWidget *Log6; + GtkWidget *Log7; + GtkWidget *Log8; + GtkWidget *Log9; + GtkWidget *Log10; + GtkWidget *Log11; + GtkWidget *Log12; + GtkWidget *Log13; + GtkWidget *Log15; + GtkWidget *Log14; + GtkWidget *Log16; + GtkWidget *Log31; + GtkWidget *Log; + GtkWidget *Log30; + GtkWidget *frame5; + GtkWidget *table4; + GtkWidget *Log27; + GtkWidget *Log26; + GtkWidget *Log25; + GtkWidget *Log24; + GtkWidget *Log23; + GtkWidget *Log22; + GtkWidget *Log21; + GtkWidget *Log20; + GtkWidget *Log28; + GtkWidget *hbuttonbox19; + GtkWidget *button66; + GtkWidget *button67; + + Logging = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (Logging), "Logging", Logging); + gtk_container_set_border_width (GTK_CONTAINER (Logging), 5); + gtk_window_set_title (GTK_WINDOW (Logging), _("Logging")); + gtk_window_set_position (GTK_WINDOW (Logging), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (Logging), FALSE, FALSE, FALSE); + + vbox23 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox23); + gtk_object_set_data_full (GTK_OBJECT (Logging), "vbox23", vbox23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox23); + gtk_container_add (GTK_CONTAINER (Logging), vbox23); + gtk_container_set_border_width (GTK_CONTAINER (vbox23), 5); + + hbox15 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox15); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbox15", hbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox15); + gtk_box_pack_start (GTK_BOX (vbox23), hbox15, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox15), 5); + + frame4 = gtk_frame_new (_("EE Logs")); + gtk_widget_ref (frame4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "frame4", frame4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (hbox15), frame4, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame4), 5); + + table3 = gtk_table_new (8, 3, FALSE); + gtk_widget_ref (table3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "table3", table3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table3); + gtk_container_add (GTK_CONTAINER (frame4), table3); + gtk_container_set_border_width (GTK_CONTAINER (table3), 5); + gtk_table_set_row_spacings (GTK_TABLE (table3), 5); + gtk_table_set_col_spacings (GTK_TABLE (table3), 5); + + Log0 = gtk_check_button_new_with_label (_("Cpu Log")); + gtk_widget_ref (Log0); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log0", Log0, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log0); + gtk_table_attach (GTK_TABLE (table3), Log0, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log1 = gtk_check_button_new_with_label (_("Mem Log")); + gtk_widget_ref (Log1); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log1", Log1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log1); + gtk_table_attach (GTK_TABLE (table3), Log1, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log2 = gtk_check_button_new_with_label (_("Hw Log")); + gtk_widget_ref (Log2); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log2", Log2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log2); + gtk_table_attach (GTK_TABLE (table3), Log2, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log3 = gtk_check_button_new_with_label (_("Dma Log")); + gtk_widget_ref (Log3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log3", Log3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log3); + gtk_table_attach (GTK_TABLE (table3), Log3, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log4 = gtk_check_button_new_with_label (_("Bios Log")); + gtk_widget_ref (Log4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log4", Log4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log4); + gtk_table_attach (GTK_TABLE (table3), Log4, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log5 = gtk_check_button_new_with_label (_("Elf Log")); + gtk_widget_ref (Log5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log5", Log5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log5); + gtk_table_attach (GTK_TABLE (table3), Log5, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log6 = gtk_check_button_new_with_label (_("Fpu Log")); + gtk_widget_ref (Log6); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log6", Log6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log6); + gtk_table_attach (GTK_TABLE (table3), Log6, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log7 = gtk_check_button_new_with_label (_("MMI Log")); + gtk_widget_ref (Log7); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log7", Log7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log7); + gtk_table_attach (GTK_TABLE (table3), Log7, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log8 = gtk_check_button_new_with_label (_("VU0 Log")); + gtk_widget_ref (Log8); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log8", Log8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log8); + gtk_table_attach (GTK_TABLE (table3), Log8, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log9 = gtk_check_button_new_with_label (_("Cop0 Log")); + gtk_widget_ref (Log9); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log9", Log9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log9); + gtk_table_attach (GTK_TABLE (table3), Log9, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log10 = gtk_check_button_new_with_label (_("Vif Log")); + gtk_widget_ref (Log10); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log10", Log10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log10); + gtk_table_attach (GTK_TABLE (table3), Log10, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log11 = gtk_check_button_new_with_label (_("SPR Log")); + gtk_widget_ref (Log11); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log11", Log11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log11); + gtk_table_attach (GTK_TABLE (table3), Log11, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log12 = gtk_check_button_new_with_label (_("GIF Log")); + gtk_widget_ref (Log12); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log12", Log12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log12); + gtk_table_attach (GTK_TABLE (table3), Log12, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log13 = gtk_check_button_new_with_label (_("Sif Log")); + gtk_widget_ref (Log13); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log13", Log13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log13); + gtk_table_attach (GTK_TABLE (table3), Log13, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log15 = gtk_check_button_new_with_label (_("VU Micro Log")); + gtk_widget_ref (Log15); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log15", Log15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log15); + gtk_table_attach (GTK_TABLE (table3), Log15, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log14 = gtk_check_button_new_with_label (_("IPU Log")); + gtk_widget_ref (Log14); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log14", Log14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log14); + gtk_table_attach (GTK_TABLE (table3), Log14, 1, 2, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log16 = gtk_check_button_new_with_label (_("RPC Log")); + gtk_widget_ref (Log16); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log16", Log16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log16); + gtk_table_attach (GTK_TABLE (table3), Log16, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log31 = gtk_check_button_new_with_label (_("Log to STDOUT")); + gtk_widget_ref (Log31); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log31", Log31, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log31); + gtk_table_attach (GTK_TABLE (table3), Log31, 2, 3, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log = gtk_check_button_new_with_label (_("Log")); + gtk_widget_ref (Log); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log", Log, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log); + gtk_table_attach (GTK_TABLE (table3), Log, 2, 3, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log30 = gtk_check_button_new_with_label (_("SYMs Log")); + gtk_widget_ref (Log30); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log30", Log30, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log30); + gtk_table_attach (GTK_TABLE (table3), Log30, 2, 3, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + frame5 = gtk_frame_new (_("IOP Logs")); + gtk_widget_ref (frame5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "frame5", frame5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (hbox15), frame5, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame5), 5); + + table4 = gtk_table_new (8, 2, FALSE); + gtk_widget_ref (table4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "table4", table4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table4); + gtk_container_add (GTK_CONTAINER (frame5), table4); + gtk_container_set_border_width (GTK_CONTAINER (table4), 5); + gtk_table_set_row_spacings (GTK_TABLE (table4), 5); + gtk_table_set_col_spacings (GTK_TABLE (table4), 5); + + Log27 = gtk_check_button_new_with_label (_("Cdr Log")); + gtk_widget_ref (Log27); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log27", Log27, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log27); + gtk_table_attach (GTK_TABLE (table4), Log27, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log26 = gtk_check_button_new_with_label (_("Gte Log")); + gtk_widget_ref (Log26); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log26", Log26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log26); + gtk_table_attach (GTK_TABLE (table4), Log26, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log25 = gtk_check_button_new_with_label (_("Pad Log")); + gtk_widget_ref (Log25); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log25", Log25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log25); + gtk_table_attach (GTK_TABLE (table4), Log25, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log24 = gtk_check_button_new_with_label (_("Dma Log")); + gtk_widget_ref (Log24); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log24", Log24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log24); + gtk_table_attach (GTK_TABLE (table4), Log24, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log23 = gtk_check_button_new_with_label (_("Bios Log")); + gtk_widget_ref (Log23); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log23", Log23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log23); + gtk_table_attach (GTK_TABLE (table4), Log23, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log22 = gtk_check_button_new_with_label (_("Hw Log")); + gtk_widget_ref (Log22); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log22", Log22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log22); + gtk_table_attach (GTK_TABLE (table4), Log22, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log21 = gtk_check_button_new_with_label (_("Mem Log")); + gtk_widget_ref (Log21); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log21", Log21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log21); + gtk_table_attach (GTK_TABLE (table4), Log21, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log20 = gtk_check_button_new_with_label (_("IOP Log")); + gtk_widget_ref (Log20); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log20", Log20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log20); + gtk_table_attach (GTK_TABLE (table4), Log20, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log28 = gtk_check_button_new_with_label (_("GPU Log")); + gtk_widget_ref (Log28); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log28", Log28, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log28); + gtk_table_attach (GTK_TABLE (table4), Log28, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + hbuttonbox19 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox19); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbuttonbox19", hbuttonbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox19); + gtk_box_pack_start (GTK_BOX (vbox23), hbuttonbox19, TRUE, TRUE, 0); + + button66 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button66); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button66", button66, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button66); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button66); + GTK_WIDGET_SET_FLAGS (button66, GTK_CAN_DEFAULT); + + button67 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button67); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button67", button67, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button67); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button67); + GTK_WIDGET_SET_FLAGS (button67, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button66), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button67), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Cancel), + NULL); + + return Logging; +} + +GtkWidget* +create_CmdLine (void) +{ + GtkWidget *CmdLine; + GtkWidget *vbox24; + GtkWidget *GtkLabel_Text; + GtkWidget *hbox17; + GtkWidget *GtkEntry_dCMDLINE; + GtkWidget *GtkLabel_Note; + GtkWidget *hbuttonbox20; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + CmdLine = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (CmdLine), "CmdLine", CmdLine); + gtk_container_set_border_width (GTK_CONTAINER (CmdLine), 5); + gtk_window_set_title (GTK_WINDOW (CmdLine), _("Program arguments")); + gtk_window_set_position (GTK_WINDOW (CmdLine), GTK_WIN_POS_CENTER); + gtk_window_set_modal (GTK_WINDOW (CmdLine), TRUE); + gtk_window_set_policy (GTK_WINDOW (CmdLine), FALSE, FALSE, FALSE); + + vbox24 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox24); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "vbox24", vbox24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox24); + gtk_container_add (GTK_CONTAINER (CmdLine), vbox24); + gtk_container_set_border_width (GTK_CONTAINER (vbox24), 5); + + GtkLabel_Text = gtk_label_new (_("Fill in the command line arguments for opened program:")); + gtk_widget_ref (GtkLabel_Text); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkLabel_Text", GtkLabel_Text, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Text); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Text, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Text), 0.1, 0.5); + + hbox17 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox17); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "hbox17", hbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox17); + gtk_box_pack_start (GTK_BOX (vbox24), hbox17, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox17), 5); + + GtkEntry_dCMDLINE = gtk_entry_new_with_max_length (255); + gtk_widget_ref (GtkEntry_dCMDLINE); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkEntry_dCMDLINE", GtkEntry_dCMDLINE, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_dCMDLINE); + gtk_box_pack_start (GTK_BOX (hbox17), GtkEntry_dCMDLINE, TRUE, TRUE, 0); + gtk_tooltips_set_tip (tooltips, GtkEntry_dCMDLINE, _("If you don't know what to write leave it blank"), NULL); + + GtkLabel_Note = gtk_label_new (_("Note: this is intented for developers only.")); + gtk_widget_ref (GtkLabel_Note); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkLabel_Note", GtkLabel_Note, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Note); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Note, FALSE, FALSE, 0); + + hbuttonbox20 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox20); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "hbuttonbox20", hbuttonbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox20); + gtk_box_pack_start (GTK_BOX (vbox24), hbuttonbox20, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnArguments_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnArguments_Cancel), + NULL); + + gtk_object_set_data (GTK_OBJECT (CmdLine), "tooltips", tooltips); + + return CmdLine; +} + +GtkWidget* +create_MemWrite32 (void) +{ + GtkWidget *MemWrite32; + GtkWidget *vbox25; + GtkWidget *hbox18; + GtkWidget *label27; + GtkWidget *label25; + GtkWidget *GtkEntry_Mem; + GtkWidget *hbox19; + GtkWidget *label28; + GtkWidget *label26; + GtkWidget *GtkEntry_Data; + GtkWidget *hbuttonbox22; + GtkWidget *button71; + GtkWidget *button72; + + MemWrite32 = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (MemWrite32), "MemWrite32", MemWrite32); + gtk_container_set_border_width (GTK_CONTAINER (MemWrite32), 5); + gtk_window_set_title (GTK_WINDOW (MemWrite32), _("memWrite32")); + gtk_window_set_position (GTK_WINDOW (MemWrite32), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (MemWrite32), FALSE, FALSE, FALSE); + + vbox25 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox25); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "vbox25", vbox25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox25); + gtk_container_add (GTK_CONTAINER (MemWrite32), vbox25); + gtk_container_set_border_width (GTK_CONTAINER (vbox25), 5); + + hbox18 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox18); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbox18", hbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox18); + gtk_box_pack_start (GTK_BOX (vbox25), hbox18, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox18), 5); + + label27 = gtk_label_new (_("Address ")); + gtk_widget_ref (label27); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label27", label27, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label27); + gtk_box_pack_start (GTK_BOX (hbox18), label27, FALSE, FALSE, 0); + + label25 = gtk_label_new (_("0x")); + gtk_widget_ref (label25); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label25", label25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label25); + gtk_box_pack_start (GTK_BOX (hbox18), label25, FALSE, FALSE, 0); + + GtkEntry_Mem = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_Mem); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "GtkEntry_Mem", GtkEntry_Mem, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Mem); + gtk_box_pack_start (GTK_BOX (hbox18), GtkEntry_Mem, TRUE, TRUE, 0); + + hbox19 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox19); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbox19", hbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox19); + gtk_box_pack_start (GTK_BOX (vbox25), hbox19, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox19), 5); + + label28 = gtk_label_new (_("Data ")); + gtk_widget_ref (label28); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label28", label28, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label28); + gtk_box_pack_start (GTK_BOX (hbox19), label28, FALSE, FALSE, 0); + + label26 = gtk_label_new (_("0x")); + gtk_widget_ref (label26); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label26", label26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label26); + gtk_box_pack_start (GTK_BOX (hbox19), label26, FALSE, FALSE, 0); + + GtkEntry_Data = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_Data); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "GtkEntry_Data", GtkEntry_Data, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Data); + gtk_box_pack_start (GTK_BOX (hbox19), GtkEntry_Data, TRUE, TRUE, 0); + + hbuttonbox22 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox22); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbuttonbox22", hbuttonbox22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox22); + gtk_box_pack_start (GTK_BOX (vbox25), hbuttonbox22, TRUE, TRUE, 0); + + button71 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button71); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "button71", button71, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button71); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button71); + GTK_WIDGET_SET_FLAGS (button71, GTK_CAN_DEFAULT); + + button72 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button72); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "button72", button72, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button72); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button72); + GTK_WIDGET_SET_FLAGS (button72, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button71), "clicked", + GTK_SIGNAL_FUNC (OnMemWrite32_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button72), "clicked", + GTK_SIGNAL_FUNC (OnMemWrite32_Cancel), + NULL); + + return MemWrite32; +} + diff --git a/Linux/GladeGui.h b/Linux/GladeGui.h new file mode 100644 index 0000000000..111115a9d5 --- /dev/null +++ b/Linux/GladeGui.h @@ -0,0 +1,17 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_MainWindow (void); +GtkWidget* create_AboutDlg (void); +GtkWidget* create_ConfDlg (void); +GtkWidget* create_CpuDlg (void); +GtkWidget* create_DebugWnd (void); +GtkWidget* create_SetPCDlg (void); +GtkWidget* create_SetBPADlg (void); +GtkWidget* create_SetBPCDlg (void); +GtkWidget* create_DumpCDlg (void); +GtkWidget* create_DumpRDlg (void); +GtkWidget* create_Logging (void); +GtkWidget* create_CmdLine (void); +GtkWidget* create_MemWrite32 (void); diff --git a/Linux/GtkGui.c b/Linux/GtkGui.c new file mode 100644 index 0000000000..134cc45dc6 --- /dev/null +++ b/Linux/GtkGui.c @@ -0,0 +1,1481 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Linux.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + +static int needreset = 1; +int confret; +int confplug=0; + +_PS2EgetLibType PS2EgetLibType = NULL; +_PS2EgetLibVersion2 PS2EgetLibVersion2 = NULL; +_PS2EgetLibName PS2EgetLibName = NULL; + +// Helper Functions +void FindPlugins(); + +// Functions Callbacks +void OnFile_LoadElf(); +void OnFile_Exit(); +void OnEmu_Run(); +void OnEmu_Reset(); +void OnEmu_Arguments(); +void OnConf_Gs(); +void OnConf_Pads(); +void OnConf_Cpu(); +void OnConf_Conf(); +void OnLanguage(GtkMenuItem *menuitem, gpointer user_data); +void OnHelp_Help(); +void OnHelp_About(); + +GtkWidget *Window; +GtkWidget *CmdLine; //2002-09-28 (Florin) +GtkWidget *ConfDlg; +GtkWidget *AboutDlg; +GtkWidget *DebugWnd; +GtkWidget *LogDlg; +GtkWidget *FileSel; + +GtkAccelGroup *AccelGroup; + +typedef struct { + GtkWidget *Combo; + GList *glist; + char plist[255][255]; + int plugins; +} PluginConf; + +PluginConf GSConfS; +PluginConf PAD1ConfS; +PluginConf PAD2ConfS; +PluginConf SPU2ConfS; +PluginConf CDVDConfS; +PluginConf DEV9ConfS; +PluginConf USBConfS; +PluginConf FWConfS; +PluginConf BiosConfS; + +void StartGui() { + GtkWidget *Menu; + GtkWidget *Item; + int i; + + Window = create_MainWindow(); + gtk_window_set_title(GTK_WINDOW(Window), "PCSX2 v" PCSX2_VERSION); + +#ifndef NEW_LOGGING + Item = lookup_widget(Window, "GtkMenuItem_Logging"); + gtk_widget_set_sensitive(Item, FALSE); +#endif + + Item = lookup_widget(Window, "GtkMenuItem_Language"); + Menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(Item), Menu); + + for (i=0; iExecute(); +} + +void OnFile_RunCD() { + efile = 2; + RunExecute(1); +} + +void OnRunElf_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(elfname, File); + gtk_widget_destroy(FileSel); + needreset = 1; + efile = 1; + RunExecute(1); +} + +void OnRunElf_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnFile_LoadElf() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Psx Elf File")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnFile_Exit() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256]; + + // with this the problem with plugins that are linked with the pthread + // library is solved + + dir = opendir(Config.PluginsDir); + if (dir != NULL) { + while ((ent = readdir(dir)) != NULL) { + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) continue; + } + } + + printf(_("PCSX2 Quitting\n")); + if (UseGui) gtk_main_quit(); + SysClose(); + if (UseGui) gtk_exit(0); + else exit(0); +} + +void OnEmu_Run() { + RunExecute(1); +} + +void OnEmu_Reset() { + needreset = 1; +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + GtkWidget *Item; + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "GtkMenuItem_LoadSlot%d", i+1); + Item = lookup_widget(Window, str); + if (Slots[i] == -1) + gtk_widget_set_sensitive(Item, FALSE); + else + gtk_widget_set_sensitive(Item, TRUE); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "sstates/%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %d"), num+1); + else sprintf (Text, _("*PCSX*: Error Saving State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnStates_Load1() { States_Load(0); } +void OnStates_Load2() { States_Load(1); } +void OnStates_Load3() { States_Load(2); } +void OnStates_Load4() { States_Load(3); } +void OnStates_Load5() { States_Load(4); } + +void OnLoadOther_Ok() { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + + efile = 2; + RunExecute(0); + + ret = LoadState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Loaded State %s"), str); + else sprintf (Text, _("*PCSX*: Error Loading State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnLoadOther_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnStates_LoadOther() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +void OnSaveOther_Ok() { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + RunExecute(0); + + ret = SaveState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %s"), str); + else sprintf (Text, _("*PCSX*: Error Saving State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnSaveOther_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnStates_SaveOther() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +//2002-09-28 (Florin) +void OnArguments_Ok() { + GtkWidget *widgetCmdLine; + char *str; + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + str = gtk_entry_get_text(GTK_ENTRY(widgetCmdLine)); + memcpy(args, str, 256); + + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnArguments_Cancel() { + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnEmu_Arguments() { + GtkWidget *widgetCmdLine; + + CmdLine = create_CmdLine(); + gtk_window_set_title(GTK_WINDOW(CmdLine), _("Program arguments")); + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + gtk_entry_set_text(GTK_ENTRY(widgetCmdLine), args); + //args exported by ElfHeader.h + gtk_widget_show_all(CmdLine); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} +//------------------- + +void OnConf_Gs() { + gtk_widget_set_sensitive(Window, FALSE); + GSconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Pads() { + gtk_widget_set_sensitive(Window, FALSE); + PAD1configure(); + if (strcmp(Config.PAD1, Config.PAD2)) PAD2configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Spu2() { + gtk_widget_set_sensitive(Window, FALSE); + SPU2configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Cdvd() { + gtk_widget_set_sensitive(Window, FALSE); + CDVDconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Dev9() { + gtk_widget_set_sensitive(Window, FALSE); + DEV9configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Usb() { + gtk_widget_set_sensitive(Window, FALSE); + USBconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Fw() { + gtk_widget_set_sensitive(Window, FALSE); + FWconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +GtkWidget *CpuDlg; + +void OnCpu_Ok() { + GtkWidget *Btn; + long t; + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + Config.Regcaching = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Patches"); + Config.Patch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + t = Config.Cpu; + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Cpu"); + Config.Cpu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (t != Config.Cpu) { + cpuRestartCPU(); + } + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + Config.VUrec = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_PsxOut"); + Config.PsxOut = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + gtk_widget_destroy(CpuDlg); + + SaveConfig(); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnCpu_Cancel() { + gtk_widget_destroy(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + + +void OnConf_Cpu() { + GtkWidget *Btn; + + CpuDlg = create_CpuDlg(); + gtk_window_set_title(GTK_WINDOW(CpuDlg), _("Configuration")); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Cpu"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Cpu); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_PsxOut"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.PsxOut); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Regcaching); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.VUrec); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Patches"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Patch); + +#ifndef CPU_LOG + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + gtk_widget_set_sensitive(Btn, FALSE); + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + gtk_widget_set_sensitive(Btn, FALSE); +#endif + + gtk_widget_show_all(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +#define FindComboText(combo,list,conf) \ + if (strlen(conf) > 0) { \ + int i; \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(conf, list[i-2])) { \ + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), list[i-1]); \ + break; \ + } \ + } \ + } + +#define GetComboText(combo,list,conf) \ + { \ + int i; \ + char *tmp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(tmp, list[i-1])) { \ + strcpy(conf, list[i-2]); \ + break; \ + } \ + } \ + } + +void OnConfConf_Ok() { + GetComboText(GSConfS.Combo, GSConfS.plist, Config.GS) + GetComboText(PAD1ConfS.Combo, PAD1ConfS.plist, Config.PAD1); + GetComboText(PAD2ConfS.Combo, PAD2ConfS.plist, Config.PAD2); + GetComboText(SPU2ConfS.Combo, SPU2ConfS.plist, Config.SPU2); + GetComboText(CDVDConfS.Combo, CDVDConfS.plist, Config.CDVD); + GetComboText(DEV9ConfS.Combo, DEV9ConfS.plist, Config.DEV9); + GetComboText(USBConfS.Combo, USBConfS.plist, Config.USB); + GetComboText(FWConfS.Combo, FWConfS.plist, Config.FW); + GetComboText(BiosConfS.Combo, BiosConfS.plist, Config.Bios); + + SaveConfig(); + + if (confplug == 0) { + ReleasePlugins(); + LoadPlugins(); + } + + needreset = 1; + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 1; +} + +void OnConfConf_Cancel() { + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 0; +} + +#define ConfPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) conf(); \ + SysCloseLibrary(drv); + +#define TestPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + int ret = 0; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) { \ + ret = conf(); \ + if (ret == 0) \ + SysMessage(_("This plugin reports that should work correctly")); \ + else SysMessage(_("This plugin reports that should not work correctly")); \ + } \ + SysCloseLibrary(drv); + +void OnConfConf_GsConf() { + ConfPlugin(_GSconfigure, GSConfS, Config.GS, "GSconfigure"); +} + +void OnConfConf_GsTest() { + TestPlugin(_GStest, GSConfS, Config.GS, "GStest"); +} + +void OnConfConf_GsAbout() { + ConfPlugin(_GSabout, GSConfS, Config.GS, "GSabout"); +} + +void OnConfConf_Pad1Conf() { + ConfPlugin(_PADconfigure, PAD1ConfS, Config.PAD1, "PADconfigure"); +} + +void OnConfConf_Pad1Test() { + TestPlugin(_PADtest, PAD1ConfS, Config.PAD1, "PADtest"); +} + +void OnConfConf_Pad1About() { + ConfPlugin(_PADabout, PAD1ConfS, Config.PAD1, "PADabout"); +} + +void OnConfConf_Pad2Conf() { + ConfPlugin(_PADconfigure, PAD2ConfS, Config.PAD2, "PADconfigure"); +} + +void OnConfConf_Pad2Test() { + TestPlugin(_PADtest, PAD2ConfS, Config.PAD2, "PADtest"); +} + +void OnConfConf_Pad2About() { + ConfPlugin(_PADabout, PAD2ConfS, Config.PAD2, "PADabout"); +} + +void OnConfConf_Spu2Conf() { + ConfPlugin(_SPU2configure, SPU2ConfS, Config.SPU2, "SPU2configure"); +} + +void OnConfConf_Spu2Test() { + TestPlugin(_SPU2test, SPU2ConfS, Config.SPU2, "SPU2test"); +} + +void OnConfConf_Spu2About() { + ConfPlugin(_SPU2about, SPU2ConfS, Config.SPU2, "SPU2about"); +} + +void OnConfConf_CdvdConf() { + ConfPlugin(_CDVDconfigure, CDVDConfS, Config.CDVD, "CDVDconfigure"); +} + +void OnConfConf_CdvdTest() { + TestPlugin(_CDVDtest, CDVDConfS, Config.CDVD, "CDVDtest"); +} + +void OnConfConf_CdvdAbout() { + ConfPlugin(_CDVDabout, CDVDConfS, Config.CDVD, "CDVDabout"); +} + +void OnConfConf_Dev9Conf() { + ConfPlugin(_DEV9configure, DEV9ConfS, Config.DEV9, "DEV9configure"); +} + +void OnConfConf_Dev9Test() { + TestPlugin(_DEV9test, DEV9ConfS, Config.DEV9, "DEV9test"); +} + +void OnConfConf_Dev9About() { + ConfPlugin(_DEV9about, DEV9ConfS, Config.DEV9, "DEV9about"); +} + +void OnConfConf_UsbConf() { + ConfPlugin(_USBconfigure, USBConfS, Config.USB, "USBconfigure"); +} + +void OnConfConf_UsbTest() { + TestPlugin(_USBtest, USBConfS, Config.USB, "USBtest"); +} + +void OnConfConf_UsbAbout() { + ConfPlugin(_USBabout, USBConfS, Config.USB, "USBabout"); +} + +void OnConfConf_FWConf() { + ConfPlugin(_FWconfigure, FWConfS, Config.FW, "FWconfigure"); +} + +void OnConfConf_FWTest() { + TestPlugin(_FWtest, FWConfS, Config.FW, "FWtest"); +} + +void OnConfConf_FWAbout() { + ConfPlugin(_FWabout, FWConfS, Config.FW, "FWabout"); +} + +#define ConfCreatePConf(name, type) \ + type##ConfS.Combo = lookup_widget(ConfDlg, "GtkCombo_" name); \ + gtk_combo_set_popdown_strings(GTK_COMBO(type##ConfS.Combo), type##ConfS.glist); \ + FindComboText(type##ConfS.Combo, type##ConfS.plist, Config.type); \ + +void UpdateConfDlg() { + FindPlugins(); + + ConfCreatePConf("Gs", GS); + ConfCreatePConf("Pad1", PAD1); + ConfCreatePConf("Pad2", PAD2); + ConfCreatePConf("Spu2", SPU2); + ConfCreatePConf("Cdvd", CDVD); + ConfCreatePConf("Dev9", DEV9); + ConfCreatePConf("Usb", USB); + ConfCreatePConf("FW", FW); + ConfCreatePConf("Bios", Bios); +} + +void OnPluginsPath_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.PluginsDir, File); + if (Config.PluginsDir[strlen(Config.PluginsDir)-1] != '/') + strcat(Config.PluginsDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnPluginsPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_PluginsPath() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Plugins Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnBiosPath_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.BiosDir, File); + if (Config.BiosDir[strlen(Config.BiosDir)-1] != '/') + strcat(Config.BiosDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnBiosPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_BiosPath() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Bios Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnConf_Conf() { + FindPlugins(); + + ConfDlg = create_ConfDlg(); + gtk_window_set_title(GTK_WINDOW(ConfDlg), _("Configuration")); + + UpdateConfDlg(); + + gtk_widget_show_all(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +GtkWidget *CmdLine; +GtkWidget *ListDV; +GtkWidget *SetPCDlg, *SetPCEntry; +GtkWidget *SetBPADlg, *SetBPAEntry; +GtkWidget *SetBPCDlg, *SetBPCEntry; +GtkWidget *DumpCDlg, *DumpCTEntry, *DumpCFEntry; +GtkWidget *DumpRDlg, *DumpRTEntry, *DumpRFEntry; +GtkWidget *MemWriteDlg, *MemEntry, *DataEntry; +GtkAdjustment *DebugAdj; +static u32 dPC; +static u32 dBPA = -1; +static u32 dBPC = -1; +static char nullAddr[256]; +int DebugMode; // 0 - EE | 1 - IOP + +#include "R3000A.h" +#include "PsxMem.h" + +void UpdateDebugger() { + GtkWidget *item; + char *str; + int i; + GList *list = NULL; + u32 pc; + + DebugAdj->value = (gfloat)dPC/4; + + gtk_list_clear_items(GTK_LIST(ListDV), 0, 23); + + for (i=0; i<23; i++) { + u32 *mem; + pc = dPC + i*4; + if (DebugMode) { + mem = (u32*)PSXM(pc); + } else + mem = PSM(pc); + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", pc); str = nullAddr; } + else str = disR5900Fasm(*mem, pc); + item = gtk_list_item_new_with_label(str); + gtk_widget_show(item); + list = g_list_append(list, item); + } + gtk_list_append_items(GTK_LIST(ListDV), list); +} + +void OnDebug_Close() { + ClosePlugins(); + gtk_widget_destroy(DebugWnd); + gtk_main_quit(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnDebug_ScrollChange(GtkAdjustment *adj) { + dPC = (u32)adj->value*4; + dPC&= ~0x3; + + UpdateDebugger(); +} + +void OnSetPC_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetPCEntry)); + + sscanf(str, "%lx", &dPC); + dPC&= ~0x3; + + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetPC_Cancel() { + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetPC() { + SetPCDlg = create_SetPCDlg(); + + SetPCEntry = lookup_widget(SetPCDlg, "GtkEntry_dPC"); + + gtk_widget_show_all(SetPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPA_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetBPAEntry)); + + sscanf(str, "%lx", &dBPA); + dBPA&= ~0x3; + + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPA_Cancel() { + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPA() { + SetBPADlg = create_SetBPADlg(); + + SetBPAEntry = lookup_widget(SetBPADlg, "GtkEntry_BPA"); + + gtk_widget_show_all(SetBPADlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPC_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetBPCEntry)); + + sscanf(str, "%lx", &dBPC); + + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPC_Cancel() { + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPC() { + SetBPCDlg = create_SetBPCDlg(); + + SetBPCEntry = lookup_widget(SetBPCDlg, "GtkEntry_BPC"); + + gtk_widget_show_all(SetBPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_ClearBPs() { + dBPA = -1; + dBPC = -1; +} + +void OnDumpC_Ok() { + FILE *f; + char *str = gtk_entry_get_text(GTK_ENTRY(DumpCFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = gtk_entry_get_text(GTK_ENTRY(DumpCTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", addrf); str = nullAddr; } + else str = disR5900Fasm(*mem, addrf); + + fprintf(f, "%s\n", str); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpC_Cancel() { + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_DumpCode() { + DumpCDlg = create_DumpCDlg(); + + DumpCFEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCF"); + DumpCTEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCT"); + + gtk_widget_show_all(DumpCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDumpR_Ok() { + FILE *f; + char *str = gtk_entry_get_text(GTK_ENTRY(DumpRFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = gtk_entry_get_text(GTK_ENTRY(DumpRTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + u32 out; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) out = 0; + else out = *mem; + + fwrite(&out, 4, 1, f); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpR_Cancel() { + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_RawDump() { + DumpRDlg = create_DumpRDlg(); + + DumpRFEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRF"); + DumpRTEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRT"); + + gtk_widget_show_all(DumpRDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_Step() { + Cpu->Step(); + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Skip() { + cpuRegs.pc+= 4; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +int HasBreakPoint(u32 pc) { + if (pc == dBPA) return 1; + if (DebugMode == 0) { + if ((cpuRegs.cycle - 10) <= dBPC && + (cpuRegs.cycle + 10) >= dBPC) return 1; + } else { + if ((psxRegs.cycle - 100) <= dBPC && + (psxRegs.cycle + 100) >= dBPC) return 1; + } + return 0; +} + +void OnDebug_Go() { + for (;;) { + if (HasBreakPoint(cpuRegs.pc)) break; + Cpu->Step(); + } + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Log() { + Log = 1 - Log; +} + +void OnDebug_EEMode() { + DebugMode = 0; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_IOPMode() { + DebugMode = 1; + dPC = psxRegs.pc; + UpdateDebugger(); +} + +void OnMemWrite32_Ok() { + char *mem = gtk_entry_get_text(GTK_ENTRY(MemEntry)); + char *data = gtk_entry_get_text(GTK_ENTRY(DataEntry)); + + printf("memWrite32: %s, %s\n", mem, data); + memWrite32(strtol(mem, (char**)NULL, 0), strtol(data, (char**)NULL, 0)); + + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnMemWrite32_Cancel() { + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_memWrite32() { + MemWriteDlg = create_MemWrite32(); + + MemEntry = lookup_widget(MemWriteDlg, "GtkEntry_Mem"); + DataEntry = lookup_widget(MemWriteDlg, "GtkEntry_Data"); + + gtk_widget_show_all(MemWriteDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); + + UpdateDebugger(); +} + +void OnDebug_Debugger() { + GtkWidget *scroll; + + if (OpenPlugins() == -1) return; + if (needreset) { SysReset(); needreset = 0; } + + if (!efile) + efile=GetPS2ElfName(elfname); + if (efile) + loadElfFile(elfname); + efile=0; + + dPC = cpuRegs.pc; + + DebugWnd = create_DebugWnd(); + + ListDV = lookup_widget(DebugWnd, "GtkList_DisView"); + scroll = lookup_widget(DebugWnd, "GtkVScrollbar_VList"); + + DebugAdj = GTK_RANGE(scroll)->adjustment; + DebugAdj->lower = (gfloat)0x00000000/4; + DebugAdj->upper = (gfloat)0xffffffff/4; + DebugAdj->step_increment = (gfloat)1; + DebugAdj->page_increment = (gfloat)20; + DebugAdj->page_size = (gfloat)23; + + gtk_signal_connect(GTK_OBJECT(DebugAdj), + "value_changed", GTK_SIGNAL_FUNC(OnDebug_ScrollChange), + NULL); + + UpdateDebugger(); + + gtk_widget_show_all(DebugWnd); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +void OnLogging_Ok() { + GtkWidget *Btn; + char str[32]; + int i, ret; + + for (i=0; i<17; i++) { + sprintf(str, "Log%d", i); + Btn = lookup_widget(LogDlg, str); + ret = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (ret) varLog|= 1<d_name); \ + type##ConfS.glist = g_list_append(type##ConfS.glist, type##ConfS.plist[type##ConfS.plugins-1]); \ +} + +void FindPlugins() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256],name[256]; + + GSConfS.plugins = 0; CDVDConfS.plugins = 0; DEV9ConfS.plugins = 0; + PAD1ConfS.plugins = 0; PAD2ConfS.plugins = 0; SPU2ConfS.plugins = 0; + USBConfS.plugins = 0; FWConfS.plugins = 0; BiosConfS.plugins = 0; + GSConfS.glist = NULL; CDVDConfS.glist = NULL; DEV9ConfS.glist = NULL; + PAD1ConfS.glist = NULL; PAD2ConfS.glist = NULL; SPU2ConfS.glist = NULL; + USBConfS.glist = NULL; FWConfS.glist = NULL; BiosConfS.glist = NULL; + + dir = opendir(Config.PluginsDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.PluginsDir); + return; + } + while ((ent = readdir(dir)) != NULL) { + u32 version; + u32 type; + + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) { + printf("%s\n", dlerror()); continue; + } + + PS2EgetLibType = (_PS2EgetLibType) dlsym(Handle, "PS2EgetLibType"); + PS2EgetLibName = (_PS2EgetLibName) dlsym(Handle, "PS2EgetLibName"); + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) dlsym(Handle, "PS2EgetLibVersion2"); + if (PS2EgetLibType == NULL || PS2EgetLibName == NULL || PS2EgetLibVersion2 == NULL) + continue; + type = PS2EgetLibType(); + + if (type & PS2E_LT_GS) { + version = PS2EgetLibVersion2(PS2E_LT_GS); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_GS_VERSION) { + ComboAddPlugin(GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)dlsym(Handle, "PADquery"); + version = PS2EgetLibVersion2(PS2E_LT_PAD); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(PAD1); + if (query() & 0x2) + ComboAddPlugin(PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2EgetLibVersion2(PS2E_LT_SPU2); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_SPU2_VERSION) { + ComboAddPlugin(SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2EgetLibVersion2(PS2E_LT_CDVD); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_CDVD_VERSION) { + ComboAddPlugin(CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2EgetLibVersion2(PS2E_LT_DEV9); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_DEV9_VERSION) { + ComboAddPlugin(DEV9); + } else SysPrintf("DEV9Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2EgetLibVersion2(PS2E_LT_USB); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_USB_VERSION) { + ComboAddPlugin(USB); + } else SysPrintf("USBPlugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2EgetLibVersion2(PS2E_LT_FW); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_FW_VERSION) { + ComboAddPlugin(FW); + } else SysPrintf("FWPlugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_FW_VERSION); + } + } + closedir(dir); + + dir = opendir(Config.BiosDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.BiosDir); + return; + } + + while ((ent = readdir(dir)) != NULL) { + struct stat buf; + char description[50]; //2002-09-28 (Florin) + + sprintf (plugin, "%s%s", Config.BiosDir, ent->d_name); + if (stat(plugin, &buf) == -1) continue; +// if (buf.st_size < (1024*512)) continue; + if (buf.st_size > (1024*4096)) continue; //2002-09-28 (Florin) + if (!IsBIOS(ent->d_name, description)) continue;//2002-09-28 (Florin) + + BiosConfS.plugins+=2; + sprintf(description, "%s (%s)", description, ent->d_name); + strcpy(BiosConfS.plist[BiosConfS.plugins-1], description);//2002-09-28 (Florin) modified + strcpy(BiosConfS.plist[BiosConfS.plugins-2], ent->d_name); + BiosConfS.glist = g_list_append(BiosConfS.glist, BiosConfS.plist[BiosConfS.plugins-1]); + } + closedir(dir); +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + if (!UseGui) { printf("%s\n",msg); return; } + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), _("PCSX2 Msg")); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label(_("Ok")); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} diff --git a/Linux/Linux.h b/Linux/Linux.h new file mode 100644 index 0000000000..cc966bb54f --- /dev/null +++ b/Linux/Linux.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + +#include "Common.h" + +typedef struct { + char lang[256]; +} _langs; + +_langs *langs; +unsigned int langsMax; + +extern int UseGui; +char cfgfile[256]; + +int LoadConfig(); +void SaveConfig(); + +void StartGui(); +void RunGui(); + +int Pcsx2Configure(); + +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); + +#endif /* __LINUX_H__ */ diff --git a/Linux/LnxMain.c b/Linux/LnxMain.c new file mode 100644 index 0000000000..ac8e48c86c --- /dev/null +++ b/Linux/LnxMain.c @@ -0,0 +1,327 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "Linux.h" + + +static char Pcsx2Help[] = { + "Pcsx2 " PCSX2_VERSION "\n" + " pcsx2 [options] [file]\n" + "\toptions:\n" + "\t-nogui\t\tDon't open GtkGui\n" + "\t-cfg FILE\tLoads desired configuration file (def:Pcsx2.cfg)\n" + "\t-psxout\t\tEnable psx output\n" + "\t-h -help\tThis help\n" + "\tfile\t\tLoads file\n" +}; + +int UseGui = 1; +int needReset = 1; + + +int main(int argc, char *argv[]) { + char *file = NULL; + char elfname[256]; + char *lang; + int runcd=0; + int efile; + int i; + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, "Langs"); + textdomain(PACKAGE); +#endif + + strcpy(cfgfile, "Pcsx2.cfg"); + + for (i=1; iExecute(); + + return 0; +} + +DIR *dir; + +void InitLanguages() { + dir = opendir("Langs"); +} + +char *GetLanguageNext() { + struct dirent *ent; + + if (dir == NULL) return NULL; + for (;;) { + ent = readdir(dir); + if (ent == NULL) return NULL; + + if (!strcmp(ent->d_name, ".")) continue; + if (!strcmp(ent->d_name, "..")) continue; + break; + } + + return ent->d_name; +} + +void CloseLanguages() { + if (dir) closedir(dir); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +int StatesC = 0; + +void KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + switch (ev->key) { + case XK_F1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); +/* if (ret == 0) + sprintf(Text, _("*PCSX*: Saved State %d"), StatesC+1); + else sprintf(Text, _("*PCSX*: Error Saving State %d"), StatesC+1); + GPU_displayText(Text); + if (ShowPic) { ShowPic = 0; gpuShowPic(); }*/ + break; + case XK_F2: + if (StatesC < 4) StatesC++; + else StatesC = 0; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); +/* GPU_freeze(2, (GPUFreeze_t *)&StatesC); + if (ShowPic) { ShowPic = 0; gpuShowPic(); }*/ + break; + case XK_F3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); +/* if (ret == 0) + sprintf(Text, _("*PCSX*: Loaded State %d"), StatesC+1); + else sprintf(Text, _("*PCSX*: Error Loading State %d"), StatesC+1); + GPU_displayText(Text);*/ + break; + case XK_F5: +// if (sio2.hackedRecv==0x1D100) sio2.hackedRecv=0x1100; +// else sio2.hackedRecv=0x1D100; +// SysPrintf("hackedRecv : %x\n", sio2.hackedRecv); + break; + + case XK_F8: + GSmakeSnapshot("snap/"); + break; +#ifdef CPU_LOG + case XK_F9: + Log = 1 - Log; + SysPrintf("Log : %d\n", Log); + break; + case XK_F10: +/* if (varLog & 0x40000000) varLog&=~0x40000000; + else varLog|= 0x40000000; + SysPrintf("varLog %x\n", varLog);*/ + SysPrintf("hack\n"); + psxSu32(0x30) = 0x20000; +// psMu32(0x8010c904) = 0; + break; +#endif + case XK_F11: + SysPrintf("Open\n"); + cdCaseopen = 1; + break; + case XK_F12: + SysPrintf("Close\n"); + cdCaseopen = 0; + break; + case XK_Escape: + signal(SIGINT, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + ClosePlugins(); + if (!UseGui) exit(0); + RunGui(); + break; + default: + GSkeyEvent(ev); + break; + } +} + +int SysInit() { + mkdir("sstates", 0755); + mkdir("memcards", 0755); + + cpuInit(); + while (LoadPlugins() == -1) { + if (Pcsx2Configure() == 0) exit(1); + } + + return 0; +} + +void SysReset() { + cpuReset(); +} + +void SysClose() { + cpuShutdown(); + ReleasePlugins(); + + if (emuLog != NULL) fclose(emuLog); +} + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (Config.PsxOut) { printf("%s", msg); fflush(stdout); } +#ifdef EMU_LOG + fprintf(emuLog, "%s", msg); +#endif +} + +void *SysLoadLibrary(char *lib) { + return dlopen(lib, RTLD_NOW); +} + +void *SysLoadSym(void *lib, char *sym) { + return dlsym(lib, sym); +} + +char *SysLibError() { + return dlerror(); +} + +void SysCloseLibrary(void *lib) { + dlclose(lib); +} + +void SysUpdate() { + KeyEvent(PAD1keyEvent()); + KeyEvent(PAD1keyEvent()); +} + +void SysRunGui() { + RunGui(); +} + +void *SysMmap(uptr base, u32 size) { + return mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +} + +void SysMunmap(uptr base, u32 size) { + munmap((uptr*)base, size); +} + diff --git a/Linux/Makefile b/Linux/Makefile new file mode 100644 index 0000000000..b970e83545 --- /dev/null +++ b/Linux/Makefile @@ -0,0 +1,106 @@ +# +# PCSX2 Makefile for Linux +# + + +all: pcsx2 + +CPU = i386 +#CPU = x86_64 + +PCSX2 = pcsx2 + +CC = gcc +RM = rm -f +AR = ar +STRIP = strip + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double +SSEOPTIMIZE = -O4 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double -mfpmath=sse -march=athlon64 + +FLAGS = -D__LINUX__ -DENABLE_NLS -DPACKAGE=\"pcsx2\" +# this includes the option -rdynamic and we don't want that +LIBST = $(shell gtk-config --libs) +LIBS = $(subst -rdynamic,,${LIBST}) -lz -lpthread + +OBJS = ../Counters.o ../DebugTools/DisR5900.o ../Elfheader.o \ + ../Hw.o ../Memory.o ../Misc.o ../GS.o ../FiFo.o ../Sif.o\ + ../Plugins.o ../R5900.o ../InterTables.o ../Interpreter.o \ + ../COP0.o ../FPU.o ../VU0.o ../VU0micro.o ../VU1micro.o ../VUflags.o \ + ../MMI.o ../Vif.o ../SPR.o ../DebugTools/DisR5900asm.o ../IPU/IPU.o \ + ../DebugTools/DisVU0Micro.o ../DebugTools/DisVU1Micro.o ../CDVDiso.o ../CDVDisodrv.o \ + ../DebugTools/cpuopsDebug.o ../IPU/yuv2rgb.o \ + ../IPU/mpeg2lib/Idct.o ../IPU/mpeg2lib/Mpeg.o \ + ../Patch.o ../Stats.o ../VUops.o ../Cache.o ../VifDma.o ../FPU2.o +OBJS+= ../R3000A.o ../DebugTools/DisR3000A.o ../PsxBios.o \ + ../PsxMem.o ../PsxInterpreter.o ../PsxCounters.o ../PsxHw.o \ + ../PsxDma.o ../Gte.o ../Sio.o ../CdRom.o ../Mdec.o \ + ../Decode_XA.o ../PsxGPU.o ../PsxSio2.o ../CDVD.o + +OBJS+= LnxMain.o Config.o GtkGui.o +OBJS+= GladeGui.o GladeFuncs.o + +ifeq (${CPU}, i386) + OBJS+= ../x86/iR5900.o ../ix86-32/iR5900Arit.o ../ix86-32/iR5900AritImm.o \ + ../ix86-32/iR5900Branch.o ../ix86-32/iR5900Jump.o ../ix86-32/iR5900LoadStore.o \ + ../ix86-32/iR5900Move.o ../ix86-32/iR5900MultDiv.o ../ix86-32/iR5900Shift.o \ + ../x86/recCOP2.o ../x86/iCP0.o \ + ../x86/iFPU.o ../x86/iMMI.o ../x86/iVUmicro.o \ + ../x86/iVU0micro.o ../x86/iVU1micro.o ../x86/iR3000A.o + OBJS+= ../x86/ix86/ix86.o ../x86/ix86/ix86_fpu.o \ + ../x86/ix86/ix86_3dnow.o ../x86/ix86/ix86_mmx.o \ + ../x86/ix86/ix86_cpudetect.o ../x86/ix86/ix86_sse.o + FLAGS+= -I../ix86-32 -I../x86 +endif + +ifeq (${CPU}, x86_64) + OBJS+= ../x86/iR5900.o ../x86-64/iR5900Arit.o ../x86-64/iR5900AritImm.o \ + ../x86-64/iR5900Branch.o ../x86-64/iR5900Jump.o ../x86-64/iR5900LoadStore.o \ + ../x86-64/iR5900Move.o ../x86-64/iR5900MultDiv.o ../x86-64/iR5900Shift.o \ + ../x86/recCOP2.o ../x86/iCP0.o \ + ../x86/iFPU.o ../x86/iMMI.o ../x86/iVUmicro.o \ + ../x86/iVU0micro.o ../x86/iVU1micro.o ../x86/iR3000A.o + OBJS+= ../x86/ix86/ix86.o ../x86/ix86/ix86_fpu.o \ + ../x86/ix86/ix86_3dnow.o ../x86/ix86/ix86_mmx.o \ + ../x86/ix86/ix86_cpudetect.o ../x86/ix86/ix86_sse.o + FLAGS+= -I../x86-64 -I../x86 +endif + +DEPS:= $(OBJS:.o=.d) +ROBJS:= $(OBJS:.o=.ro) +RSOBJS:= $(OBJS:.o=.rso) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I../IPU -I../DebugTools ${FLAGS} +CSSEFLAGS = -Wall ${SSEOPTIMIZE} -I. -I.. -I../IPU -I../DebugTools ${FLAGS} +CFLAGS+= $(shell gtk-config --cflags) +CSSEFLAGS+= $(shell gtk-config --cflags) + +pcsx2: ${OBJS} + ${CC} ${CFLAGS} ${OBJS} -o pcsx2 ${LIBS} +# ${STRIP} pcsx2 + +release: ${ROBJS} + ${CC} ${CFLAGS} ${ROBJS} -o pcsx2 ${LIBS} +# ${STRIP} pcsx2 + +release-sse: ${RSOBJS} + ${CC} ${CSSEFLAGS} ${RSOBJS} -o pcsx2 ${LIBS} +# ${STRIP} pcsx2 + +.PHONY: clean pcsx2 release release-sse + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} ${ROBJS} ${RSOBJS} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.ro: %.c + ${CC} ${CFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.rso: %.c + ${CC} ${CSSEFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} + + diff --git a/Linux/Makefile.cfg.in b/Linux/Makefile.cfg.in new file mode 100644 index 0000000000..e53cbd54af --- /dev/null +++ b/Linux/Makefile.cfg.in @@ -0,0 +1,6 @@ + +CC = @CC@ +LIBS = @LIBS@ @GTK_LIBS@ +CFLAGS = @CFLAGS@ @GTK_CFLAGS@ +STRIP = @STRIP@ +RM = @RM@ diff --git a/Linux/configure.in b/Linux/configure.in new file mode 100644 index 0000000000..fecf117d1b --- /dev/null +++ b/Linux/configure.in @@ -0,0 +1,33 @@ +dnl Process this file with autoconf to produce a configure script. +dnl by Linuzappz +dnl autoconf version 2.13 + +AC_INIT(LnxMain.c) +AM_INIT_AUTOMAKE(PCSX2, 0.9) +AM_MAINTAINTER_MODE +AC_PROG_CC +AC_CHECK_PROG(STRIP, strip, strip) +AC_CHECK_PROG(RM, rm, rm) + +CFLAGS="" + +dnl check for libraries + +dnl gtk2=yes + +AC_MSG_CHECKING(gtk+) + +AC_CHECK_PROG(GTK-CONFIG, gtk-config, gtk-config) + +dnl end + +AC_SUBST(CFLAGS) +AC_SUBST(OBJS) +AC_SUBST(LIBS) +AC_SUBST(STRIP) +AC_SUBST(RM) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) + +AC_OUTPUT(Makefile.cfg) + diff --git a/Linux/pcsx2.glade b/Linux/pcsx2.glade new file mode 100644 index 0000000000..d8fb94848b --- /dev/null +++ b/Linux/pcsx2.glade @@ -0,0 +1,4413 @@ + + + + + Pcsx2 + pcsx2 + + + .pixmaps + C + False + True + False + False + False + GladeGui.c + GladeGui.h + GladeCalls.c + GladeCalls.h + GladeFuncs.c + GladeFuncs.h + + + + GtkWindow + MainWindow + 200 + + destroy + OnDestroy + Tue, 19 Feb 2002 22:15:57 GMT + + PCSX + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox1 + False + 0 + + + GtkMenuBar + GtkMenuBar_Menu + GTK_SHADOW_OUT + + 0 + False + False + + + + GtkMenuItem + GtkMenuItem_File + + False + + + GtkMenu + GtkMenuItem_File_menu + + + GtkMenuItem + run_cd1 + + activate + OnFile_RunCD + Tue, 17 Jun 2003 17:35:02 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_LoadElf + + activate + OnFile_LoadElf + Fri, 05 Apr 2002 19:47:01 GMT + + + False + + + + GtkMenuItem + separator2 + False + + + + GtkMenuItem + states1 + + False + + + GtkMenu + states1_menu + + + GtkMenuItem + load1 + + False + + + GtkMenu + load1_menu + + + GtkMenuItem + slot_1 + + activate + OnStates_Load1 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_3 + + activate + OnStates_Load2 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_4 + + activate + OnStates_Load3 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_5 + + activate + OnStates_Load4 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_2 + + activate + OnStates_Load5 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + other1 + + activate + OnStates_LoadOther + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + + + GtkMenuItem + save1 + + False + + + GtkMenu + save1_menu + + + GtkMenuItem + slot_6 + + activate + OnStates_Save1 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_7 + + activate + OnStates_Save2 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_8 + + activate + OnStates_Save3 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_9 + + activate + OnStates_Save4 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_10 + + activate + OnStates_Save5 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + other2 + + activate + OnStates_SaveOther + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + + + + + GtkMenuItem + GtkMenuItem_Exit + + activate + OnFile_Exit + Thu, 06 Dec 2001 03:20:01 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Emulator + + False + + + GtkMenu + GtkMenuItem_Emulator_menu + + + GtkMenuItem + GtkMenuItem_Run + + activate + OnEmu_Run + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Reset + + activate + OnEmu_Reset + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Arguments + + activate + OnEmu_Arguments + Sun, 29 Sep 2002 04:59:42 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Configuration + + False + + + GtkMenu + GtkMenuItem_Configuration_menu + + + GtkMenuItem + GtkMenuItem_PluginsBios + + activate + OnConf_Conf + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + separator3 + False + + + + GtkMenuItem + GtkMenuItem_Graphics + + activate + OnConf_Gs + Fri, 05 Apr 2002 23:41:41 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Controllers + + activate + OnConf_Pads + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Sound + + activate + OnConf_Spu2 + Sat, 06 Jul 2002 05:35:47 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Cdvdrom + + activate + OnConf_Cdvd + Sat, 06 Jul 2002 05:35:47 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Dev9 + + activate + OnConf_Dev9 + Tue, 02 Sep 2003 17:41:31 GMT + + + False + + + + GtkMenuItem + separator4 + False + + + + GtkMenuItem + GtkMenuItem_Cpu + + activate + OnConf_Cpu + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Language + + False + + + + GtkMenuItem + GtkMenuItem_Debug + + False + + + GtkMenu + GtkMenuItem_Debug_menu + + + GtkMenuItem + GtkMenuItem_EnterDebugger + + activate + OnDebug_Debugger + Mon, 27 May 2002 04:44:12 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Logging + + activate + OnDebug_Logging + Wed, 26 Jun 2002 05:04:32 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Help + + False + + + GtkMenu + GtkMenuItem_Help_menu + + + GtkMenuItem + GtkMenuItem_About + + activate + OnHelp_About + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + + + + + + GtkWindow + AboutDlg + 10 + Pcsx About + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox2 + False + 0 + + + GtkPacker + packer1 + 0 + 0 + 0 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox1 + False + 0 + + 0 + True + True + + + + GtkVBox + vbox4 + False + 0 + + 0 + True + True + + + + GtkLabel + GtkAbout_LabelVersion + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkFrame + frame1 + 5 + 0 + GTK_SHADOW_ETCHED_IN + + 0 + False + False + + + + GtkVBox + vbox6 + 5 + False + 0 + + + GtkLabel + GtkAbout_LabelAuthors + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + + + + GtkPixmap + pixmap1 + pcsxAbout.xpm + 0.5 + 0.5 + 0 + 0 + True + + 0 + True + True + + + + + + GtkFrame + frame2 + 5 + 0 + GTK_SHADOW_ETCHED_IN + + 0 + False + False + + + + GtkVBox + vbox5 + 5 + False + 0 + + + GtkLabel + GtkAbout_LabelGreets + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnHelpAbout_Ok + Thu, 06 Dec 2001 03:47:23 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + ConfDlg + 10 + Conf + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox12 + False + 0 + + + GtkTable + table2 + 14 + 2 + False + 0 + 15 + + 0 + True + True + + + + GtkCombo + GtkCombo_Pad1 + False + True + False + True + False + + + 0 + 1 + 4 + 5 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry4 + True + True + True + 0 + + + + + + GtkCombo + GtkCombo_Pad2 + False + True + False + True + False + + + 1 + 2 + 4 + 5 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry5 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox6 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 5 + 6 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_PAD2configure + True + True + + clicked + OnConfConf_Pad2Conf + Tue, 25 Dec 2001 05:40:52 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD2test + True + True + + clicked + OnConfConf_Pad2Test + Tue, 25 Dec 2001 05:41:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD2about + True + True + + clicked + OnConfConf_Pad2About + Tue, 25 Dec 2001 05:41:18 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox7 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 5 + 6 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_PAD1configure + True + True + + clicked + OnConfConf_Pad1Conf + Tue, 25 Dec 2001 05:38:17 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD1test + True + True + + clicked + OnConfConf_Pad1Test + Tue, 25 Dec 2001 05:39:35 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD1about + True + True + + clicked + OnConfConf_Pad1About + Tue, 25 Dec 2001 05:39:58 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox8 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 2 + 3 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_GSconfigure + True + True + + clicked + OnConfConf_GsConf + Fri, 05 Apr 2002 23:40:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_GStest + True + True + + clicked + OnConfConf_GsTest + Fri, 05 Apr 2002 23:40:08 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_GSabout + True + True + + clicked + OnConfConf_GsAbout + Fri, 05 Apr 2002 23:40:14 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + GtkLabel_Graphics + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_FirstController + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_SecondController + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 3 + 4 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Gs + False + True + False + True + False + + + 0 + 1 + 1 + 2 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry2 + True + True + True + 0 + + + + + + GtkLabel + GtkLabel_Sound + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Spu2 + False + True + False + True + False + + + 1 + 2 + 1 + 2 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox12 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 2 + 3 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_SPU2configure + True + True + + clicked + OnConfConf_Spu2Conf + Sat, 20 Apr 2002 16:13:27 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_SPU2test + True + True + + clicked + OnConfConf_Spu2Test + Sat, 20 Apr 2002 16:14:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_SPU2about + True + True + + clicked + OnConfConf_Spu2About + Sat, 20 Apr 2002 16:14:16 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkCombo + GtkCombo_Dev9 + False + True + False + True + False + + + 0 + 1 + 7 + 8 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry3 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox21 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 8 + 9 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_DEV9configure + True + True + + clicked + OnConfConf_Dev9Conf + Thu, 21 Aug 2003 18:36:30 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_DEV9test + True + True + + clicked + OnConfConf_Dev9Test + Thu, 21 Aug 2003 18:36:38 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_DEV9about + True + True + + clicked + OnConfConf_Dev9About + Thu, 21 Aug 2003 18:36:48 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + label23 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 6 + 7 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_Cdvdrom + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 6 + 7 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Cdvd + False + True + False + True + False + + + 1 + 2 + 7 + 8 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry2 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox13 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 8 + 9 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_CDVDconfigure + True + True + + clicked + OnConfConf_CdvdConf + Fri, 05 Jul 2002 21:44:43 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_CDVDtest + True + True + + clicked + OnConfConf_CdvdTest + Fri, 05 Jul 2002 21:44:30 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_CDVDabout + True + True + + clicked + OnConfConf_CdvdAbout + Fri, 05 Jul 2002 21:44:07 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + label29 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 9 + 10 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Usb + False + True + False + True + False + + + 0 + 1 + 10 + 11 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry4 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox23 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 11 + 12 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_USBconfigure + True + True + + clicked + OnConfConf_UsbConf + Mon, 01 Mar 2004 14:21:01 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_USBtest + True + True + + clicked + OnConfConf_UsbTest + Mon, 01 Mar 2004 14:21:09 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_USBabout + True + True + + clicked + OnConfConf_UsbAbout + Mon, 01 Mar 2004 14:21:14 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkCombo + GtkCombo_Bios + False + True + False + True + False + + + 1 + 2 + 13 + 14 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry7 + True + True + True + 0 + + + + + + GtkCombo + GtkCombo_FireWire + False + True + False + True + False + + + 1 + 2 + 10 + 11 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry5 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox24 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 11 + 12 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_FWconfigure + True + True + + clicked + OnConfConf_FWConf + Wed, 17 Nov 2004 03:59:27 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_FWtest + True + True + + clicked + OnConfConf_FWTest + Wed, 17 Nov 2004 03:59:33 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_FireWireabout + True + True + + clicked + OnConfConf_FWAbout + Wed, 17 Nov 2004 04:00:56 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + label30 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 9 + 10 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_Bios + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 12 + 13 + 0 + 0 + False + False + False + False + False + False + + + + + + GtkHBox + hbox5 + False + 14 + + 0 + True + True + + + + GtkHButtonBox + hbuttonbox11 + GTK_BUTTONBOX_START + 0 + 85 + 27 + 7 + 0 + + 0 + False + True + + + + GtkButton + GtkButton_SelectPluginsDir + True + True + + clicked + OnConfConf_PluginsPath + Mon, 14 Jan 2002 19:18:13 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_SelectBiosDir + True + True + + clicked + OnConfConf_BiosPath + Mon, 14 Jan 2002 19:12:02 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox10 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnConfConf_Ok + Tue, 25 Dec 2001 05:19:01 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Cancel + True + True + + clicked + OnConfConf_Cancel + Tue, 25 Dec 2001 05:19:16 GMT + + + GTK_RELIEF_NORMAL + + + + + + + + GtkWindow + CpuDlg + 5 + Cpu + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox8 + False + 0 + + + GtkHBox + hbox20 + False + 0 + + 0 + True + True + + + + GtkFrame + GtkFrame_Options + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox15 + 5 + False + 0 + + + GtkCheckButton + GtkCheckButton_PsxOut + True + + False + True + + 0 + False + False + + + + + GtkCheckButton + GtkCheckButton_Patches + True + + False + True + + 0 + False + False + + + + + + + + GtkFrame + frame6 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox26 + 5 + False + 0 + + + GtkCheckButton + GtkCheckButton_Cpu + True + + False + True + + 0 + False + False + + + + + GtkCheckButton + GtkCheckButton_RegCaching + True + + False + True + + 0 + False + False + + + + + GtkCheckButton + GtkCheckButton_VUrec + True + + False + True + + 0 + False + False + + + + + + + GtkHButtonBox + hbuttonbox3 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnCpu_Ok + Fri, 07 Dec 2001 04:34:39 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Cancel + True + True + + clicked + OnCpu_Cancel + Fri, 07 Dec 2001 04:34:55 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + DebugWnd + 5 + PCSX2 Debugger + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox16 + 5 + False + 0 + + + GtkHBox + hbox16 + False + 5 + + 0 + True + True + + + + GtkRadioButton + GtkRadioButton_EE + True + + toggled + OnDebug_EEMode + Wed, 26 Jun 2002 22:06:10 GMT + + + False + True + Debug + + 0 + False + False + + + + + GtkRadioButton + GtkRadioButton_IOP + True + + toggled + OnDebug_IOPMode + Wed, 26 Jun 2002 22:06:29 GMT + + + False + True + Debug + + 0 + False + False + + + + + + GtkHBox + hbox6 + 5 + False + 0 + + 0 + True + True + + + + GtkHBox + hbox7 + False + 0 + + 0 + True + True + + + + GtkScrolledWindow + scrolledwindow1 + 320 + GTK_POLICY_ALWAYS + GTK_POLICY_NEVER + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + 0 + True + True + + + + GtkViewport + viewport1 + GTK_SHADOW_IN + + + GtkList + GtkList_DisView + GTK_SELECTION_SINGLE + + + + + + GtkVScrollbar + GtkVScrollbar_VList + GTK_UPDATE_CONTINUOUS + 0 + 0 + 412 + 1 + 20 + 2 + + 0 + True + True + + + + + + GtkVBox + vbox22 + False + 0 + + 0 + True + True + + + + GtkVButtonBox + vbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button52 + True + True + + clicked + OnDebug_Step + Mon, 27 May 2002 19:06:08 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button53 + True + True + + clicked + OnDebug_Skip + Mon, 03 Jun 2002 04:34:40 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button65 + True + True + + clicked + OnDebug_Go + Mon, 27 May 2002 19:06:18 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button64 + True + True + + clicked + OnDebug_Log + Mon, 27 May 2002 19:06:29 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkVButtonBox + vbuttonbox3 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button58 + True + True + + clicked + OnDebug_SetPC + Mon, 27 May 2002 18:53:12 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button59 + True + True + + clicked + OnDebug_SetBPA + Mon, 27 May 2002 19:17:57 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button60 + True + True + + clicked + OnDebug_SetBPC + Thu, 30 May 2002 19:08:00 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button61 + True + True + + clicked + OnDebug_ClearBPs + Fri, 31 May 2002 03:26:43 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkVButtonBox + vbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button39 + True + True + + clicked + OnDebug_DumpCode + Fri, 31 May 2002 03:29:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button40 + True + True + + clicked + OnDebug_RawDump + Fri, 31 May 2002 03:30:44 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button41 + True + True + + clicked + OnDebug_Close + Mon, 27 May 2002 04:56:26 GMT + + + GTK_RELIEF_NORMAL + + + + + + GtkVButtonBox + vbuttonbox4 + GTK_BUTTONBOX_DEFAULT_STYLE + 10 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button68 + True + True + + clicked + OnDebug_memWrite32 + Sat, 01 Nov 2003 04:23:51 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button69 + True + True + + GTK_RELIEF_NORMAL + + + + GtkButton + button70 + True + True + + GTK_RELIEF_NORMAL + + + + + + + + GtkWindow + SetPCDlg + 5 + SetPCDlg + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox17 + 5 + False + 5 + + + GtkLabel + label9 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox8 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label10 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_dPC + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox14 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button42 + True + True + + clicked + OnSetPC_Ok + Mon, 27 May 2002 18:45:45 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button43 + True + True + + clicked + OnSetPC_Cancel + Mon, 27 May 2002 18:45:57 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + SetBPADlg + 5 + SetBreakPoint Addr + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox18 + 5 + False + 5 + + + GtkLabel + label11 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox9 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label12 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_BPA + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox15 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button44 + True + True + + clicked + OnSetBPA_Ok + Mon, 27 May 2002 19:09:57 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button45 + True + True + + clicked + OnSetBPA_Cancel + Mon, 27 May 2002 19:11:00 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + SetBPCDlg + 5 + SetBreakPoint Addr + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox19 + 5 + False + 5 + + + GtkLabel + label13 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox10 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label14 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_BPC + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox16 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button46 + True + True + + clicked + OnSetBPC_Ok + Fri, 31 May 2002 03:58:44 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button47 + True + True + + clicked + OnSetBPC_Cancel + Fri, 31 May 2002 03:58:38 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + DumpCDlg + 5 + Dump code + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox20 + 5 + False + 5 + + + GtkLabel + label15 + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox11 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label16 + + GTK_JUSTIFY_CENTER + True + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpCF + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHBox + hbox12 + 5 + False + 2 + + 0 + True + True + + + + GtkLabel + label17 + 45 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpCT + True + True + True + 8 + + + 0 + True + True + + + + + + GtkLabel + label21 + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox17 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button48 + True + True + + clicked + OnDumpC_Ok + Fri, 31 May 2002 03:37:47 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button49 + True + True + + clicked + OnDumpC_Cancel + Fri, 31 May 2002 03:37:40 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + DumpRDlg + 5 + Raw Dump + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox21 + 5 + False + 5 + + + GtkLabel + label18 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox13 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label19 + + GTK_JUSTIFY_CENTER + True + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpRF + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHBox + hbox14 + 5 + False + 2 + + 0 + True + True + + + + GtkLabel + label20 + 45 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpRT + True + True + True + 8 + + + 0 + True + True + + + + + + GtkLabel + label22 + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox18 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button50 + True + True + + clicked + OnDumpR_Ok + Fri, 31 May 2002 03:53:48 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button51 + True + True + + clicked + OnDumpR_Cancel + Fri, 31 May 2002 03:54:09 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + Logging + 5 + Logging + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox23 + 5 + False + 5 + + + GtkHBox + hbox15 + 5 + False + 5 + + 0 + True + True + + + + GtkFrame + frame4 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkTable + table3 + 5 + 8 + 3 + False + 5 + 5 + + + GtkCheckButton + Log0 + True + + False + True + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log1 + True + + False + True + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log2 + True + + False + True + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log3 + True + + False + True + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log4 + True + + False + True + + 0 + 1 + 4 + 5 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log5 + True + + False + True + + 0 + 1 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log6 + True + + False + True + + 0 + 1 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log7 + True + + False + True + + 0 + 1 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log8 + True + + False + True + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log9 + True + + False + True + + 1 + 2 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log10 + True + + False + True + + 1 + 2 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log11 + True + + False + True + + 1 + 2 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log12 + True + + False + True + + 1 + 2 + 4 + 5 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log13 + True + + False + True + + 1 + 2 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log15 + True + + False + True + + 1 + 2 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log14 + True + + False + True + + 1 + 2 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log16 + True + + False + True + + 2 + 3 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log31 + True + + False + True + + 2 + 3 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log + True + + False + True + + 2 + 3 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log30 + True + + False + True + + 2 + 3 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + + + GtkFrame + frame5 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkTable + table4 + 5 + 8 + 2 + False + 5 + 5 + + + GtkCheckButton + Log27 + True + + False + True + + 0 + 1 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log26 + True + + False + True + + 0 + 1 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log25 + True + + False + True + + 0 + 1 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log24 + True + + False + True + + 0 + 1 + 4 + 5 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log23 + True + + False + True + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log22 + True + + False + True + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log21 + True + + False + True + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log20 + True + + False + True + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log28 + True + + False + True + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + + + + GtkHButtonBox + hbuttonbox19 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button66 + True + True + + clicked + OnLogging_Ok + Wed, 26 Jun 2002 05:20:00 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button67 + True + True + + clicked + OnLogging_Cancel + Wed, 26 Jun 2002 05:20:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + CmdLine + 5 + Program arguments + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + True + False + False + False + + + GtkVBox + vbox24 + 5 + False + 5 + + + GtkLabel + GtkLabel_Text + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox17 + 5 + False + 2 + + 0 + False + False + + + + GtkEntry + GtkEntry_dCMDLINE + If you don't know what to write leave it blank + True + True + True + 255 + + + 0 + True + True + + + + + + GtkLabel + GtkLabel_Note + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox20 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnArguments_Ok + Sat, 28 Sep 2002 13:54:37 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Cancel + True + True + + clicked + OnArguments_Cancel + Sat, 28 Sep 2002 13:54:57 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + MemWrite32 + 5 + memWrite32 + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox25 + 5 + False + 5 + + + GtkHBox + hbox18 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label27 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label25 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_Mem + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHBox + hbox19 + 5 + False + 2 + + 0 + True + True + + + + GtkLabel + label28 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label26 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_Data + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox22 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button71 + True + True + + clicked + OnMemWrite32_Ok + Sat, 01 Nov 2003 04:38:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button72 + True + True + + clicked + OnMemWrite32_Cancel + Sat, 01 Nov 2003 04:36:57 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/MMI.c b/MMI.c new file mode 100644 index 0000000000..662f324772 --- /dev/null +++ b/MMI.c @@ -0,0 +1,1475 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" + + +void MMI() { +#ifdef MMI_LOG + MMI_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_MMIPrintTable[_Funct_](); +} + +void MMI0() { + Int_MMI0PrintTable[_Sa_](); +} + +void MMI1() { + Int_MMI1PrintTable[_Sa_](); +} + +void MMI2() { + Int_MMI2PrintTable[_Sa_](); +} + +void MMI3() { + Int_MMI3PrintTable[_Sa_](); +} + +void MMI_Unknown() { + SysPrintf ("Unknown MMI opcode called\n"); +} + +//*****************MMI OPCODES********************************* + +void MADD() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[0] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +void MADDU() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[0] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +#define _PLZCW(n) { \ + sign = cpuRegs.GPR.r[_Rs_].UL[n] >> 31; \ + for (i=30; i>=0; i--) { \ + if (((cpuRegs.GPR.r[_Rs_].UL[n] >> i) & 0x1) != sign) { \ + break; \ + } \ + } \ + cpuRegs.GPR.r[_Rd_].UL[n] = 30 - i; \ +} + +void PLZCW() { + int i; + u32 sign; + + if (!_Rd_) return; + + _PLZCW (0); + _PLZCW (1); +} + +void MADD1() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[1] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MADDU1() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MFHI1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[1]; +} + +void MFLO1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MTHI1() { + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MTLO1() { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MULT1() { + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[1] = (s64)(s32)(temp & 0xffffffff); + cpuRegs.HI.UD[1] = (s64)(s32)(temp >> 32); + + /* Modified a bit . asadr */ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MULTU1() { + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.UD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void DIV1() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU1() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +#define PMFHL_CLAMP(dst, src) \ + if ((int)src > (int)0x00007fff) dst = 0x7fff; \ + else \ + if ((int)src < (int)0xffff8000) dst = 0x8000; \ + else dst = (u16)src; + +void PMFHL() { + if (!_Rd_) return; + + switch (_Sa_) { + case 0x00: // LW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + break; + + case 0x01: // UW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[3]; + break; + + case 0x02: // SLW + { + u64 TempU64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0]; + if (TempU64 >= 0x000000007fffffff) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0x000000007fffffff; + } else if (TempU64 <= 0xffffffff80000000) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0xffffffff80000000; + } else { + cpuRegs.GPR.r[_Rd_].UD[0] = (s64)cpuRegs.LO.SL[0]; + } + + TempU64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2]; + if (TempU64 >= 0x000000007fffffff) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0x000000007fffffff; + } else if (TempU64 <= 0xffffffff80000000) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0xffffffff80000000; + } else { + cpuRegs.GPR.r[_Rd_].UD[1] = (s64)cpuRegs.LO.SL[2]; + } + } + break; + + case 0x03: // LH + cpuRegs.GPR.r[_Rd_].US[0] = cpuRegs.LO.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = cpuRegs.LO.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = cpuRegs.HI.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = cpuRegs.HI.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = cpuRegs.LO.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = cpuRegs.LO.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = cpuRegs.HI.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = cpuRegs.HI.US[6]; + break; + + case 0x04: // SH + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[0], cpuRegs.LO.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[1], cpuRegs.LO.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[2], cpuRegs.HI.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[3], cpuRegs.HI.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[4], cpuRegs.LO.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[5], cpuRegs.LO.UL[3]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[6], cpuRegs.HI.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[7], cpuRegs.HI.UL[3]); + break; + } +} + +void PMTHL() { + if (_Sa_ != 0) return; + + cpuRegs.LO.UL[0] = cpuRegs.GPR.r[_Rs_].UL[0]; + cpuRegs.HI.UL[0] = cpuRegs.GPR.r[_Rs_].UL[1]; + cpuRegs.LO.UL[2] = cpuRegs.GPR.r[_Rs_].UL[2]; + cpuRegs.HI.UL[2] = cpuRegs.GPR.r[_Rs_].UL[3]; +} + +#define _PSLLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] << ( _Sa_ & 0xf ); + +void PSLLH() { + if (!_Rd_) return; + + _PSLLH(0); _PSLLH(1); _PSLLH(2); _PSLLH(3); + _PSLLH(4); _PSLLH(5); _PSLLH(6); _PSLLH(7); +} + +#define _PSRLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] >> ( _Sa_ & 0xf ); + +void PSRLH () { + if (!_Rd_) return; + + _PSRLH(0); _PSRLH(1); _PSRLH(2); _PSRLH(3); + _PSRLH(4); _PSRLH(5); _PSRLH(6); _PSRLH(7); +} + +#define _PSRAH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].SS[n] >> ( _Sa_ & 0xf ); + +void PSRAH() { + if (!_Rd_) return; + + _PSRAH(0); _PSRAH(1); _PSRAH(2); _PSRAH(3); + _PSRAH(4); _PSRAH(5); _PSRAH(6); _PSRAH(7); +} + +#define _PSLLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] << _Sa_; + +void PSLLW() { + if (!_Rd_) return; + + _PSLLW(0); _PSLLW(1); _PSLLW(2); _PSLLW(3); +} + +#define _PSRLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] >> _Sa_; + +void PSRLW() { + if (!_Rd_) return; + + _PSRLW(0); _PSRLW(1); _PSRLW(2); _PSRLW(3); +} + +#define _PSRAW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].SL[n] >> _Sa_; + +void PSRAW() { + if (!_Rd_) return; + + _PSRAW(0); _PSRAW(1); _PSRAW(2); _PSRAW(3); +} + +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +#define _PADDW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] + cpuRegs.GPR.r[_Rt_].UL[n]; + +void PADDW() { + if (!_Rd_) return; + + _PADDW(0); _PADDW(1); _PADDW(2); _PADDW(3); +} + +#define _PSUBW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] - cpuRegs.GPR.r[_Rt_].UL[n]; + +void PSUBW() { + if (!_Rd_) return; + + _PSUBW(0); _PSUBW(1); _PSUBW(2); _PSUBW(3); +} + +#define _PCGTW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCGTW() { + if (!_Rd_) return; + + _PCGTW(0); _PCGTW(1); _PCGTW(2); _PCGTW(3); +} + +#define _PMAXW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].UL[n] : cpuRegs.GPR.r[_Rt_].UL[n]; + +void PMAXW() { + if (!_Rd_) return; + + _PMAXW(0); _PMAXW(1); _PMAXW(2); _PMAXW(3); +} + +#define _PADDH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] + cpuRegs.GPR.r[_Rt_].US[n]; + +void PADDH() { + if (!_Rd_) return; + + _PADDH(0); _PADDH(1); _PADDH(2); _PADDH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PSUBH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] - cpuRegs.GPR.r[_Rt_].US[n]; + +void PSUBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PSUBH(4); _PSUBH(5); _PSUBH(6); _PSUBH(7); +} + +#define _PCGTH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + 0xFFFF : 0x0000; + +void PCGTH() { + if (!_Rd_) return; + + _PCGTH(0); _PCGTH(1); _PCGTH(2); _PCGTH(3); + _PCGTH(4); _PCGTH(5); _PCGTH(6); _PCGTH(7); +} + +#define _PMAXH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMAXH() { + if (!_Rd_) return; + + _PMAXH(0); _PMAXH(1); _PMAXH(2); _PMAXH(3); + _PMAXH(4); _PMAXH(5); _PMAXH(6); _PMAXH(7); +} + +#define _PADDB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] + cpuRegs.GPR.r[_Rt_].SC[n]; + +void PADDB() { + if (!_Rd_) return; + + _PADDB(0); _PADDB(1); _PADDB(2); _PADDB(3); + _PADDB(4); _PADDB(5); _PADDB(6); _PADDB(7); + _PADDB(8); _PADDB(9); _PADDB(10); _PADDB(11); + _PADDB(12); _PADDB(13); _PADDB(14); _PADDB(15); +} + +#define _PSUBB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] - cpuRegs.GPR.r[_Rt_].SC[n]; + +void PSUBB() { + if (!_Rd_) return; + + _PSUBB(0); _PSUBB(1); _PSUBB(2); _PSUBB(3); + _PSUBB(4); _PSUBB(5); _PSUBB(6); _PSUBB(7); + _PSUBB(8); _PSUBB(9); _PSUBB(10); _PSUBB(11); + _PSUBB(12); _PSUBB(13); _PSUBB(14); _PSUBB(15); +} + +#define _PCGTB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].SC[n] > cpuRegs.GPR.r[_Rt_].SC[n]) ? \ + 0xFF : 0x00; + +void PCGTB() { + if (!_Rd_) return; + + _PCGTB(0); _PCGTB(1); _PCGTB(2); _PCGTB(3); + _PCGTB(4); _PCGTB(5); _PCGTB(6); _PCGTB(7); + _PCGTB(8); _PCGTB(9); _PCGTB(10); _PCGTB(11); + _PCGTB(12); _PCGTB(13); _PCGTB(14); _PCGTB(15); +} + +#define _PADDSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].SL[n] + (s64)cpuRegs.GPR.r[_Rt_].SL[n]; \ + if (sTemp64 > 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000) && (sTemp64 >= 0x100000000)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PADDSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PADDSW(0); _PADDSW(1); _PADDSW(2); _PADDSW(3); +} + +#define _PSUBSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 >= 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000) && (sTemp64 >= 0x100000000)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PSUBSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBSW(0); _PSUBSW(1); _PSUBSW(2); _PSUBSW(3); +} + +void PEXTLW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[1]; +} + +void PPACW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[2]; +} + +#define _PADDSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] + (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 > 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = (s16)sTemp32; \ + } + +void PADDSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDSH(0); _PADDSH(1); _PADDSH(2); _PADDSH(3); + _PADDSH(4); _PADDSH(5); _PADDSH(6); _PADDSH(7); +} + +#define _PSUBSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] - (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 >= 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (s16)sTemp32; \ + } + +void PSUBSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBSH(0); _PSUBSH(1); _PSUBSH(2); _PSUBSH(3); + _PSUBSH(4); _PSUBSH(5); _PSUBSH(6); _PSUBSH(7); +} + +void PEXTLH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[1]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[3]; +} + +void PPACH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[4] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PADDSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] + (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 > 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PADDSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PADDSB(0); _PADDSB(1); _PADDSB(2); _PADDSB(3); + _PADDSB(4); _PADDSB(5); _PADDSB(6); _PADDSB(7); + _PADDSB(8); _PADDSB(9); _PADDSB(10); _PADDSB(11); + _PADDSB(12); _PADDSB(13); _PADDSB(14); _PADDSB(15); +} + +#define _PSUBSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] - (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 >= 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PSUBSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBSB(0); _PSUBSB(1); _PSUBSB(2); _PSUBSB(3); + _PSUBSB(4); _PSUBSB(5); _PSUBSB(6); _PSUBSB(7); + _PSUBSB(8); _PSUBSB(9); _PSUBSB(10); _PSUBSB(11); + _PSUBSB(12); _PSUBSB(13); _PSUBSB(14); _PSUBSB(15); +} + +void PEXTLB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[1]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[1]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[3]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[3]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[5]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[5]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[7]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[7]; +} + +void PPACB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rt.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rt.UC[14]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[14]; +} + +#define _PEXT5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x0000001F) << 3) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x000003E0) << 6) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00007C00) << 9) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00008000) << 16); + +void PEXT5() { + if (!_Rd_) return; + + _PEXT5(0); _PEXT5(1); _PEXT5(2); _PEXT5(3); +} + +#define _PPAC5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 3) & 0x0000001F) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 6) & 0x000003E0) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 9) & 0x00007C00) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 16) & 0x00008000); + +void PPAC5() { + if (!_Rd_) return; + + _PPAC5(0); _PPAC5(1); _PPAC5(2); _PPAC5(3); +} + +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** + +#define _PABSW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = abs(cpuRegs.GPR.r[_Rt_].SL[n]); + +void PABSW() { + if (!_Rd_) return; + + _PABSW(0); _PABSW(1); _PABSW(2); _PABSW(3); +} + +#define _PCEQW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].UL[n] == cpuRegs.GPR.r[_Rt_].UL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCEQW() { + if (!_Rd_) return; + + _PCEQW(0); _PCEQW(1); _PCEQW(2); _PCEQW(3); +} + +#define _PMINW(n) \ + cpuRegs.GPR.r[_Rd_].SL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] < cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].SL[n] : cpuRegs.GPR.r[_Rt_].SL[n]; + +void PMINW() { + if (!_Rd_) return; + + _PMINW(0); _PMINW(1); _PMINW(2); _PMINW(3); +} + +void PADSBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PABSH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = abs(cpuRegs.GPR.r[_Rt_].SS[n]); + +void PABSH() { + if (!_Rd_) return; + + _PABSH(0); _PABSH(1); _PABSH(2); _PABSH(3); + _PABSH(4); _PABSH(5); _PABSH(6); _PABSH(7); +} + +#define _PCEQH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].US[n] == cpuRegs.GPR.r[_Rt_].US[n]) ? 0xFFFF : 0x0000; + +void PCEQH() { + if (!_Rd_) return; + + _PCEQH(0); _PCEQH(1); _PCEQH(2); _PCEQH(3); + _PCEQH(4); _PCEQH(5); _PCEQH(6); _PCEQH(7); +} + +#define _PMINH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] < cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMINH() { + if (!_Rd_) return; + + _PMINH(0); _PMINH(1); _PMINH(2); _PMINH(3); + _PMINH(4); _PMINH(5); _PMINH(6); _PMINH(7); +} + +#define _PCEQB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].UC[n] == \ + cpuRegs.GPR.r[_Rt_].UC[n]) ? 0xFF : 0x00; + +void PCEQB() { + if (!_Rd_) return; + + _PCEQB(0); _PCEQB(1); _PCEQB(2); _PCEQB(3); + _PCEQB(4); _PCEQB(5); _PCEQB(6); _PCEQB(7); + _PCEQB(8); _PCEQB(9); _PCEQB(10); _PCEQB(11); + _PCEQB(12); _PCEQB(13); _PCEQB(14); _PCEQB(15); +} + +#define _PADDUW(n) \ + tmp = (s64)cpuRegs.GPR.r[_Rs_].UL[n] + (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (tmp > 0xffffffff) \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0xffffffff; \ + else cpuRegs.GPR.r[_Rd_].UL[n] = (u32)tmp; + +void PADDUW () { + s64 tmp; + + if (!_Rd_) return; + + _PADDUW(0); _PADDUW(1); _PADDUW(2); _PADDUW(3); +} + +#define _PSUBUW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (u32)sTemp64; \ + } + +void PSUBUW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBUW(0); _PSUBUW(1); _PSUBUW(2); _PSUBUW(3); +} + +void PEXTUW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[3]; +} + +#define _PADDUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] + (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 > 0xFFFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0xFFFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PADDUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDUH(0); _PADDUH(1); _PADDUH(2); _PADDUH(3); + _PADDUH(4); _PADDUH(5); _PADDUH(6); _PADDUH(7); +} + +#define _PSUBUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] - (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PSUBUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBUH(0); _PSUBUH(1); _PSUBUH(2); _PSUBUH(3); + _PSUBUH(4); _PSUBUH(5); _PSUBUH(6); _PSUBUH(7); +} + +void PEXTUH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PADDUB(n) \ + Temp16 = (u16)cpuRegs.GPR.r[_Rs_].UC[n] + (u16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (Temp16 > 0xFF) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0xFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)Temp16; \ + } + +void PADDUB() { + u16 Temp16; + + if (!_Rd_) return; + + _PADDUB(0); _PADDUB(1); _PADDUB(2); _PADDUB(3); + _PADDUB(4); _PADDUB(5); _PADDUB(6); _PADDUB(7); + _PADDUB(8); _PADDUB(9); _PADDUB(10); _PADDUB(11); + _PADDUB(12); _PADDUB(13); _PADDUB(14); _PADDUB(15); +} + +#define _PSUBUB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].UC[n] - (s16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (sTemp16 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)sTemp16; \ + } + +void PSUBUB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBUB(0); _PSUBUB(1); _PSUBUB(2); _PSUBUB(3); + _PSUBUB(4); _PSUBUB(5); _PSUBUB(6); _PSUBUB(7); + _PSUBUB(8); _PSUBUB(9); _PSUBUB(10); _PSUBUB(11); + _PSUBUB(12); _PSUBUB(13); _PSUBUB(14); _PSUBUB(15); +} + +void PEXTUB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[15]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[15]; +} + +void QFSRV() { // JayteeMaster: changed a bit to avoid screw up + GPR_reg Rd; + if (!_Rd_) return; + + if (cpuRegs.sa == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; + } else { + if (cpuRegs.sa < 64) { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } else { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } + } +} + +//********END OF MMI1 OPCODES*********************************** + +//*********MMI2 OPCODES*************************************** + +#define _PMADDW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) + \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMADDW() { + _PMADDW(0, 0); + _PMADDW(1, 2); +} + +void PSLLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (s32)(cpuRegs.GPR.r[_Rt_].UL[2] << + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PSRLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].UL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +#define _PMSUBW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) - \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMSUBW() { + _PMSUBW(0, 0); + _PMSUBW(1, 2); +} + +void PMFHI() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.HI.UD[1]; +} + +void PMFLO() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.LO.UD[1]; +} + +void PINTH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PMULTW(dd, ss) { \ + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ + } \ +} + +void PMULTW() { + _PMULTW(0, 0); + _PMULTW(1, 2); +} + +#define _PDIVW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] / cpuRegs.GPR.r[_Rt_].SL[ss]; \ + cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] % cpuRegs.GPR.r[_Rt_].SL[ss]; \ + } + +void PDIVW() { + _PDIVW(0, 0); + _PDIVW(1, 2); +} + +void PCPYLD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; +} + +void PMADDH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp; */ + + temp = cpuRegs.LO.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp; */ + + temp = cpuRegs.HI.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp; */ + + temp = cpuRegs.LO.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp; */ + + temp = cpuRegs.HI.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } + +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMADH(hlr, dd, n) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[n] = temp; */\ +} + +void PHMADH() { // JayteeMaster: changed a bit to avoid screw up. Also used 0,2,4,6 instead of 0,1,2,3 + _PHMADH(LO, 0, 0); + _PHMADH(HI, 0, 2); + _PHMADH(LO, 2, 4); + _PHMADH(HI, 2, 6); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PAND() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] & cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PXOR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] ^ cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PMSUBH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = cpuRegs.LO.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = cpuRegs.HI.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = cpuRegs.LO.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = cpuRegs.HI.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMSBH(hlr, dd, n, rdd) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[rdd] = temp;*/ \ +} + +void PHMSBH() { // JayteeMaster: changed a bit to avoid screw up + _PHMSBH(LO, 0, 0, 0); + _PHMSBH(HI, 0, 2, 1); + _PHMSBH(LO, 2, 4, 2); + _PHMSBH(HI, 2, 6, 3); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PEXEH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PREVH () { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PMULTH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +#define _PDIVBW(n) \ + cpuRegs.LO.UL[n] = (s32)(cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]); \ + cpuRegs.HI.UL[n] = (s16)(cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]); \ + +void PDIVBW() { + if (cpuRegs.GPR.r[_Rt_].US[0] == 0) return; + + _PDIVBW(0); _PDIVBW(1); _PDIVBW(2); _PDIVBW(3); +} + +void PEXEW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +void PROT3W() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//*****END OF MMI2 OPCODES*********************************** + +//*************************MMI3 OPCODES************************ + +#define _PMADDUW(dd, ss) { \ + u64 tempu = (u64)((u64)cpuRegs.LO.UL[ss] | ((u64)cpuRegs.HI.UL[ss] << 32)) + \ + ((u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ +} + +void PMADDUW() { + _PMADDUW(0, 0); + _PMADDUW(1, 2); +} + +void PSRAVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].SL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].SL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PMTHI() { + cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PMTLO() { + cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PINTEH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PMULTUW(dd, ss) { \ + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ + } \ +} + +void PMULTUW() { + _PMULTUW(0, 0); + _PMULTUW(1, 2); +} + +#define _PDIVUW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] / (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + cpuRegs.HI.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] % (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + } + +void PDIVUW() { + _PDIVUW(0, 0); + _PDIVUW(1, 2); +} + +void PCPYUD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[1]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void POR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PNOR () { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = ~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); + cpuRegs.GPR.r[_Rd_].UD[1] = ~(cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]); +} + +void PEXCH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PCPYH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PEXCW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//**********************END OF MMI3 OPCODES******************** + +// obs: +// QFSRV not verified + diff --git a/Mdec.c b/Mdec.c new file mode 100644 index 0000000000..babc7a940c --- /dev/null +++ b/Mdec.c @@ -0,0 +1,521 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This code was based on the FPSE v0.08 Mdec decoder*/ + +#include +#include + +#include "PsxCommon.h" +#include "Mdec.h" + +#define FIXED + +#define CONST_BITS 8 +#define PASS1_BITS 2 + +#define FIX_1_082392200 (277) +#define FIX_1_414213562 (362) +#define FIX_1_847759065 (473) +#define FIX_2_613125930 (669) + +#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS)) + +#define DEQUANTIZE(coef,quantval) (coef) + +#define DESCALE(x,n) ((x)>>(n)) +#define RANGE(n) (n) + +#define DCTSIZE 8 +#define DCTSIZE2 64 + +static void idct1(int *block) +{ + int val = RANGE(DESCALE(block[0], PASS1_BITS+3)); + int i; + for(i=0;i>16)*(bcr&0xffff); + + if (cmd==0x60000000) { + } else + if (cmd==0x40000001) { + u8 *p = (u8*)PSXM(adr); + iqtab_init(iq_y,p); + iqtab_init(iq_uv,p+64); + } else + if ((cmd&0xf5ff0000)==0x30000000) { + mdec.rl = (u16*)PSXM(adr); + } + else { + } + + HW_DMA0_CHCR &= ~0x01000000; + psxDmaInterrupt(0); +} + +void psxDma1(u32 adr, u32 bcr, u32 chcr) { + int blk[DCTSIZE2*6]; + unsigned short *image; + int size; + +#ifdef CDR_LOG + CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command); +#endif + + if (chcr!=0x01000200) return; + + size = (bcr>>16)*(bcr&0xffff); + image = (u16*)PSXM(adr); + if (mdec.command&0x08000000) { + for (;size>0;size-=(16*16)/2,image+=(16*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb15(blk,image); + } + } else { + for (;size>0;size-=(24*16)/2,image+=(24*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb24(blk,(u8 *)image); + } + } + + HW_DMA1_CHCR &= ~0x01000000; + psxDmaInterrupt(1); +} + + +#define RUNOF(a) ((a)>>10) +#define VALOF(a) (((int)(a)<<(32-10))>>(32-10)) + +static int zscan[DCTSIZE2] = { + 0 ,1 ,8 ,16,9 ,2 ,3 ,10, + 17,24,32,25,18,11,4 ,5 , + 12,19,26,33,40,48,41,34, + 27,20,13,6 ,7 ,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +static int aanscales[DCTSIZE2] = { + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 +}; + +void iqtab_init(int *iqtab,unsigned char *iq_y) +{ +#define CONST_BITS14 14 +#define IFAST_SCALE_BITS 2 + int i; + + for(i=0;i>(CONST_BITS14-IFAST_SCALE_BITS); + } +} + +#define NOP 0xfe00 +unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) { + int i,k,q_scale,rl; + int *iqtab; + + memset (blk, 0, 6*DCTSIZE2*4); + iqtab = iq_uv; + for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4) + if (i>1) iqtab = iq_y; + + // zigzag transformation + rl = *mdec_rl++; + q_scale = RUNOF(rl); + blk[0] = iqtab[0]*VALOF(rl); + for(k = 0;;) { + rl = *mdec_rl++; + if (rl==NOP) break; + k += RUNOF(rl)+1; // skip level zero-coefficients + if (k > 63) break; + blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16; + } +// blk[0] = (blk[0] * iq_t[0] * 8) / 16; +// for(int j=1;j<64;j++) +// blk[j] = blk[j] * iq_t[j] * q_scale; + + // idct + idct(blk,k+1); + + blk+=DCTSIZE2; + } + return mdec_rl; +} + +#ifdef FIXED +#define MULR(a) ((((int)0x0000059B) * (a)) >> 10) +#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10) +#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10) +#define MULB(a) ((((int)0x00000716) * (a)) >> 10) +#else +#define MULR(a) ((int)((float)1.40200 * (a))) +#define MULG(a) ((int)((float)-0.3437 * (a))) +#define MULG2(a) ((int)((float)-0.7143 * (a))) +#define MULB(a) ((int)((float)1.77200 * (a))) +#endif + +#define MAKERGB15(r,g,b) ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) ) +#define ROUND(c) roundtbl[((c)+128+256)]//&0x3ff] +/*#define ROUND(c) round(c+128) +int round(int r) { + if (r<0) return 0; + if (r>255) return 255; + return r; +}*/ + +#define RGB15(n, Y) \ + image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B)); + +#define RGB15BW(n, Y) \ + image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y)); + +#define RGB24(n, Y) \ + image[n+2] = ROUND(Y + R); \ + image[n+1] = ROUND(Y + G); \ + image[n+0] = ROUND(Y + B); + +#define RGB24BW(n, Y) \ + image[n+2] = ROUND(Y); \ + image[n+1] = ROUND(Y); \ + image[n+0] = ROUND(Y); + +unsigned char roundtbl[256*3]; + +void round_init(void) { + int i; + for(i=0;i<256;i++) { + roundtbl[i]=0; + roundtbl[i+256]=i; + roundtbl[i+512]=255; + } +} + +void yuv2rgb15(int *blk,unsigned short *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(0, Yblk[0]); + RGB15(1, Yblk[1]); + RGB15(16, Yblk[8]); + RGB15(17, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(8, Yblk[DCTSIZE2+0]); + RGB15(9, Yblk[DCTSIZE2+1]); + RGB15(24, Yblk[DCTSIZE2+8]); + RGB15(25, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Yblk+=2) { + RGB15BW(0, Yblk[0]); + RGB15BW(1, Yblk[1]); + RGB15BW(16, Yblk[8]); + RGB15BW(17, Yblk[9]); + + RGB15BW(8, Yblk[DCTSIZE2+0]); + RGB15BW(9, Yblk[DCTSIZE2+1]); + RGB15BW(24, Yblk[DCTSIZE2+8]); + RGB15BW(25, Yblk[DCTSIZE2+9]); + } + } +} + +void yuv2rgb24(int *blk,unsigned char *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(0, Yblk[0]); + RGB24(1*3, Yblk[1]); + RGB24(16*3, Yblk[8]); + RGB24(17*3, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(8*3, Yblk[DCTSIZE2+0]); + RGB24(9*3, Yblk[DCTSIZE2+1]); + RGB24(24*3, Yblk[DCTSIZE2+8]); + RGB24(25*3, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Yblk+=2) { + RGB24BW(0, Yblk[0]); + RGB24BW(1*3, Yblk[1]); + RGB24BW(16*3, Yblk[8]); + RGB24BW(17*3, Yblk[9]); + + RGB24BW(8*3, Yblk[DCTSIZE2+0]); + RGB24BW(9*3, Yblk[DCTSIZE2+1]); + RGB24BW(24*3, Yblk[DCTSIZE2+8]); + RGB24BW(25*3, Yblk[DCTSIZE2+9]); + } + } +} + +int mdecFreeze(gzFile f, int Mode) { + + gzfreeze(&mdec, sizeof(mdec)); + + gzfreezel(iq_y); + + gzfreezel(iq_uv); + + + + return 0; + +} + + + + diff --git a/Mdec.h b/Mdec.h new file mode 100644 index 0000000000..33690c98ff --- /dev/null +++ b/Mdec.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MDEC_H__ +#define __MDEC_H__ + +void mdecInit(); +void mdecWrite0(u32 data); +void mdecWrite1(u32 data); +u32 mdecRead0(); +u32 mdecRead1(); +void psxDma0(u32 madr, u32 bcr, u32 chcr); +void psxDma1(u32 madr, u32 bcr, u32 chcr); +int mdecFreeze(gzFile f, int Mode); + +#endif /* __MDEC_H__ */ diff --git a/Memory.c b/Memory.c new file mode 100644 index 0000000000..6386e2cac8 --- /dev/null +++ b/Memory.c @@ -0,0 +1,3097 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + +RAM +--- +0x00100000-0x01ffffff this is the physical address for the ram.its cached there +0x20100000-0x21ffffff uncached +0x30100000-0x31ffffff uncached & acceleretade +0xa0000000-0xa1ffffff MIRROR might...??? +0x80000000-0x81ffffff MIRROR might... ???? + +scratch pad +---------- +0x70000000-0x70003fff scratch pad + +BIOS +---- +0x1FC00000 - 0x1FFFFFFF un-cached +0x9FC00000 - 0x9FFFFFFF cached +0xBFC00000 - 0xBFFFFFFF un-cached +*/ + +////////// +// Rewritten by zerofrog(@gmail.com) to add os virtual memory +////////// + + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#pragma warning(disable:4799) // No EMMS at end of function + +#include +#include +#include +#include + +#include "Common.h" +#include "ir5900.h" +#include "PsxMem.h" +#include "R3000A.h" +#include "psxhw.h" +#include "VUmicro.h" + +#include + +extern u32 maxrecmem; + +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +//#define FULLTLB +int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode + +#if ENABLE_GS_CACHING + +// addr can belong to locked GS memory +#define CHECK_GSMEM(addr) { \ + if( (addr) < 0x10000000 ) { \ + u32* page = GS_PAGEADDRS+((addr)>>GS_SHIFT)*(GSPAGES_MEMADDRS+1); \ + if( *(u8*)page) GSFreePage(page); \ + } \ +} \ + +#define CHECK_GSMEM_ASM() \ +{ \ + __asm cmp edx, 0x10000000 /* make sure not scratch mem*/ \ + __asm jae RegularRead \ + __asm mov edx, ecx \ + __asm shr edx, GS_SHIFT \ + __asm imul edx, (GSPAGES_MEMADDRS+1)*4 \ + __asm cmp byte ptr [edx+GS_PAGEADDRS_], 0 \ + __asm je RegularRead \ + __asm add edx, GS_PAGEADDRS_ \ + __asm sub esp, 12 \ + __asm mov dword ptr [esp+0], edx \ + __asm mov dword ptr [esp+4], eax \ + __asm mov dword ptr [esp+8], ecx \ + __asm call GSFreePage \ + __asm mov eax, dword ptr [esp+4] \ + __asm mov ecx, dword ptr [esp+8] \ + __asm add esp, 12 \ + } \ +RegularRead: \ + +//#define CHECK_GSMEM_ASM_REC() // rec everything above + +#else +#define CHECK_GSMEM(mem) +#define CHECK_GSMEM_ASM() +#define CHECK_GSMEM_ASM_REC(mem) +#endif + +u16 ba0R16(u32 mem) { +#ifdef MEM_LOG + //MEM_LOG("ba00000 Memory read16 address %x\n", mem); +#endif + +#ifdef WIN32_VIRTUAL_MEM + if (mem == 0x1a000006) { +#else + if (mem == 0xba000006) { +#endif + static int ba6; + ba6++; + if (ba6 == 3) ba6 = 0; + return ba6; + } + return 0; +} + +///////////////////////////// +// VIRTUAL MEM START +///////////////////////////// +#ifdef WIN32_VIRTUAL_MEM + +//#define VM_RETRANSLATE(mem) (PS2MEM_BASE_+mem) + +// Some games read/write between different addrs but same physical memory +// this causes major slowdowns because it goes into the exception handler, so use this (zerofrog) +u32 VM_RETRANSLATE(u32 mem) +{ + u8* p, *pbase; + if( (mem&0xffff0000) == 0x50000000 ) // reserved scratch pad mem + return PS2MEM_BASE_+mem; + + p = (u8*)dmaGetAddrBase(mem), *pbase; + + // do manual LUT since IPU/SPR seems to use addrs 0x3000xxxx quite often + if( memLUT[ (p-PS2MEM_BASE)>>12 ].aPFNs == NULL ) { + return PS2MEM_BASE_+mem; + } + + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); + + return (u32)p; +} + +PSMEMORYMAP initMemoryMap(ULONG_PTR* aPFNs, ULONG_PTR* aVFNs) +{ + PSMEMORYMAP m; + m.aPFNs = aPFNs; + m.aVFNs = aVFNs; + return m; +} + +// only do vm hack for release +#ifndef PCSX2_DEVBUILD +#define VM_HACK +#endif + +static int XmmExtendedRegOffset = 160; + +// virtual memory blocks +PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0}; +PSMEMORYMAP *memLUT = NULL; + +#define PHYSICAL_ALLOC(ptr, size, block) { \ + if(SysPhysicalAlloc(size, &block) == -1 ) \ + goto eCleanupAndExit; \ + if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \ + goto eCleanupAndExit; \ +} \ + +#define VIRTUAL_ALLOC(base, size, Protection) { \ + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \ + if( lpMemReserved == NULL || base != lpMemReserved ) \ + { \ + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \ + goto eCleanupAndExit; \ + } \ +} \ + +#define PHYSICAL_FREE(ptr, size, block) { \ + SysVirtualFree(ptr, size); \ + SysPhysicalFree(&block); \ +} \ + +#define VIRTUAL_FREE(ptr, size) { \ + VirtualFree(ptr, size, MEM_DECOMMIT); \ + VirtualFree(ptr, 0, MEM_RELEASE); \ +} \ + +static int s_testmem[4] = { 0xfafafafa, 0xbabababa, 0xbfa8123f, 0xa123fde0 }; + +INT FindXmmOffsetException(LPEXCEPTION_POINTERS pexdata) +{ + int i; + u32* p = (u32*)pexdata->ContextRecord->ExtendedRegisters; + + assert( pexdata->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); + + XmmExtendedRegOffset = 160; + + for(i = 0; i < sizeof(pexdata->ContextRecord->ExtendedRegisters)/4; ++i, ++p ) { + if( p[0] == s_testmem[0] && p[1] == s_testmem[1] && p[2] == s_testmem[2] && p[3] == s_testmem[3] ) { + XmmExtendedRegOffset = i*4; + break; + } + } + + pexdata->ContextRecord->Eip += 7; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +#if _MSC_VER < 1400 +#define VC_HANDLER _except_handler3 +#else +#define VC_HANDLER _except_handler4 +#endif + +//C's default exception handler +EXCEPTION_DISPOSITION VC_HANDLER( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +char cpp_handler_instructions[5]; +BOOL saved_handler_instructions = FALSE; + +//Exception handler that replaces C's default handler. +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +#pragma pack(1) +typedef struct _jmp_instr +{ + unsigned char jmp; + DWORD offset; +} jmp_instr; +#pragma pack() + +BOOL WriteMemory(void * loc, void * buffer, int size) +{ + DWORD o2; + HANDLE hProcess = GetCurrentProcess(); + + //change the protection of pages containing range of memory + //[loc, loc+size] to READ WRITE + DWORD old_protection; + + BOOL ret; + ret = VirtualProtectEx(hProcess, loc, size, + PAGE_READWRITE, &old_protection); + if(ret == FALSE) + return FALSE; + + ret = WriteProcessMemory(hProcess, loc, buffer, size, NULL); + + //restore old protection + VirtualProtectEx(hProcess, loc, size, old_protection, &o2); + + return (ret == TRUE); +} + +BOOL ReadMemory(void *loc, void *buffer, DWORD size) +{ + HANDLE hProcess = GetCurrentProcess(); + DWORD bytes_read = 0; + BOOL ret; + ret = ReadProcessMemory(hProcess, loc, buffer, size, &bytes_read); + return (ret == TRUE && bytes_read == size); +} + +BOOL install_my_handler() +{ + void * my_hdlr = SysPageFaultExceptionFilter; + void * cpp_hdlr = VC_HANDLER; + + jmp_instr jmp_my_hdlr; + jmp_my_hdlr.jmp = 0xE9; + + //We actually calculate the offset from __CxxFrameHandler+5 + //as the jmp instruction is 5 byte length. + jmp_my_hdlr.offset = (char*)(my_hdlr) - + ((char*)(cpp_hdlr) + 5); + + if(!saved_handler_instructions) + { + if(!ReadMemory(cpp_hdlr, cpp_handler_instructions, + sizeof(cpp_handler_instructions))) + return FALSE; + saved_handler_instructions = TRUE; + } + + return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr)); +} + +BOOL restore_cpp_handler() +{ + if(!saved_handler_instructions) + return FALSE; + else + { + void *loc = VC_HANDLER; + return WriteMemory(loc, cpp_handler_instructions, + sizeof(cpp_handler_instructions)); + } +} + +int memInit() { + + int i; + LPVOID pExtraMem = NULL; + + // release the previous reserved mem + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); + + // allocate all virtual memory + PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY); + PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM); + PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS); + + VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE); + + // reserve the left over 224Mb, don't map + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x02000000 ) + goto eCleanupAndExit; + + // reserve left over psx mem + pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_PSX+0x00200000 ) + goto eCleanupAndExit; + + // reserve gs mem + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x20000000 ) + goto eCleanupAndExit; + + // special addrs mmap + VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE); + + // alloc virtual mappings + memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16); + memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000); + for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]); + for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]); + for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]); + for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]); + + for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]); + + // map to other modes + memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + + if (psxInit() == -1) + goto eCleanupAndExit; + + // figure out xmm reg offset +// __asm movups xmm0, s_testmem +// __try { +// u8* p = 0; +// __asm { +// mov eax, dword ptr [p] +// } +// } +// __except( FindXmmOffsetException( GetExceptionInformation() ) ) { +// } + + if( !install_my_handler() ) { + SysPrintf("Failed to install custom exception handler!\n"); + return -1; + } + + return 0; + +eCleanupAndExit: + if( pExtraMem != NULL ) + VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE); + memShutdown(); + return -1; +} + +void memShutdown() +{ + VirtualFree(PS2MEM_BASE+0x02000000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_PSX+0x00200000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE); + + PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_FREE(PS2MEM_ROM, 0x00400000); + VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000); + VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000); + VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000); + PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM); + PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs + + VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000); + VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000); + VIRTUAL_FREE(PS2MEM_GS, 0x00010000); + VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000); + + VIRTUAL_FREE(PS2MEM_B80, 0x00010000); + VIRTUAL_FREE(PS2MEM_BA0, 0x00010000); + + VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE); + + _aligned_free(memLUT); memLUT = NULL; + + // reserve mem + VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { + + PSMEMORYMAP* pmap; + + if( vaddr == paddr ) + return; + + if( (vaddr>>28) != 1 && (vaddr>>28) != 9 && (vaddr>>28) != 11 ) { + pmap = &memLUT[vaddr >> 12]; + + if( pmap->aPFNs != NULL && (pmap->aPFNs != memLUT[paddr>>12].aPFNs || + pmap->aVFNs[0] != TRANSFORM_ADDR(vaddr)+(u32)PS2MEM_BASE) ) { + + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL); + pmap->aVFNs[0] = 0; + } + + *pmap = memLUT[paddr >> 12]; + } +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + +// if( vaddr >= 0x20000000 && vaddr < 0x80000000 ) { +// Cpu->Clear(vaddr&~0xfff, 0x1000/4); +// if( memLUT[vaddr>>12].aVFNs != NULL ) { +// SysMapUserPhysicalPages((void*)memLUT[vaddr>>12].aVFNs[0], 1, NULL ); +// memLUT[vaddr>>12].aVFNs = NULL; +// memLUT[vaddr>>12].aPFNs = NULL; +// } +// } +} + +#define GET_REGVALUE(code) *((u32*)&pexdata->ContextRecord->Eax + (((code)>>11)&7)) +#define GET_XMMVALUE(xmm) ((u64*)((u8*)pexdata->ContextRecord->ExtendedRegisters + XmmExtendedRegOffset + ((xmm)<<4))) + +//NOTE: A lot of the code reading depends on the registers being less than 8 +// MOV8 88/8A +// MOV16 6689 +// MOV32 89/8B +// SSEMtoR64 120f +// SSERtoM64 130f +// SSEMtoR128 280f +// SSERtoM128 290f + +#define SKIP_WRITE(pexdata) { \ + switch(code&0xff) { \ + case 0x88: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + break; \ + case 0x66: \ + assert( code&0x800000 ); \ + assert( (code&0xffff) == 0x8966 ); \ + ContextRecord->Eip += 7; \ + break; \ + case 0x89: \ + assert( code&0x8000 ); \ + ContextRecord->Eip += 6; \ + break; \ + case 0x0f: /* 130f, 230f*/ \ + assert( (code&0xffff) == 0x290f || (code&0xffff) == 0x130f ); \ + assert( code&0x800000 ); \ + ContextRecord->Eip += 7; \ + break; \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +#define SKIP_READ(pexdata) { \ + switch(code&0xff) { \ + case 0x8A: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x66: \ + if( (code&0x07000000) == 0x05000000 ) ContextRecord->Eip += 8; /* 8 for mem reads*/ \ + else ContextRecord->Eip += 4 + ((code&0x1f000000) == 0x0c000000) + !!(code&0x40000000); \ + rd = (code>>(24+3))&7; \ + break; \ + case 0x8B: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x0f: { \ + assert( (code&0xffff)==0x120f || (code&0xffff)==0x280f || (code&0xffff) == 0xb60f || (code&0xffff) == 0xb70f ); \ + if( !(code&0x800000) ) goto DefaultHandler; \ + ContextRecord->Eip += 7; \ + rd = (code>>(16+3))&7; \ + break; } \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ) +{ + u32 addr; + + C_ASSERT(sizeof(ContextRecord->Eax) == 4); + + // If the exception is not a page fault, exit. + if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + { + // call old handler + EXCEPTION_DISPOSITION d; + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // get bad virtual address + addr = (u32)ExceptionRecord->ExceptionInformation[1]; + + if( addr >= (u32)PS2MEM_BASE && addr < (u32)PS2MEM_BASE+0x60000000) { + PSMEMORYMAP* pmap; + + pmap = &memLUT[(addr-(u32)PS2MEM_BASE)>>12]; + + if( pmap->aPFNs == NULL ) { + // NOTE: this is a hack because the address is truncated and there's no way + // to tell what it's upper bits are (due to OS limitations). + pmap += 0x80000; + if( pmap->aPFNs == NULL ) { + pmap += 0x20000; + } + //else addr += 0x20000000; + } + + if( pmap->aPFNs != NULL ) { + LPVOID pnewaddr; + DWORD oldaddr = pmap->aVFNs[0]; + + if( pmap->aVFNs[0] != 0 ) { + // delete the current mapping + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL); + } + + assert( pmap->aPFNs[0] != 0 ); + + pmap->aVFNs[0] = addr&~0xfff; + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs) ) + return ExceptionContinueExecution; + + // try allocing the virtual mem + pnewaddr = VirtualAlloc((void*)(addr&~0xffff), 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs) ) + return ExceptionContinueExecution; + + SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n", + addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], pmap->aVFNs[0]); + } + } + else { + // check if vumem + + if( (addr&0xffff4000) == 0x11000000 ) { + // vu0mem + SysMapUserPhysicalPages((void*)s_psVuMem.aVFNs[1], 1, NULL); + + s_psVuMem.aVFNs[1] = addr&~0xfff; + SysMapUserPhysicalPages((void*)addr, 1, &s_psVuMem.aPFNs[1]); + + return ExceptionContinueExecution;//EXCEPTION_CONTINUE_EXECUTION; + } + } + + { + // call old handler + EXCEPTION_DISPOSITION d; + +#ifdef VM_HACK + u32 code = *(u32*)ExceptionRecord->ExceptionAddress; + u32 rd = 0; + + if( ExceptionRecord->ExceptionInformation[0] ) { + //SKIP_WRITE(ptrs); + // shouldn't be writing + } + else { + SysPrintf("vmhack "); + SKIP_READ(ptrs); + //((u32*)&ContextRecord->Eax)[rd] = 0; + return ExceptionContinueExecution; + } + +DefaultHandler: +#endif + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // continue execution + return EXCEPTION_CONTINUE_EXECUTION; +} + +u8 recMemRead8() +{ + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&~0xffff) ) { + case 0x1f400000: return psxHw4Read8(mem); + case 0x10000000: return hwRead8(mem); + case 0x1f800000: return psxHwRead8(mem); + case 0x12000000: return *(PS2MEM_BASE+(mem&~0xc00)); + case 0x14000000: + { + u32 ret = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u8*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +void _eeReadConstMem8(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-3); + assert(0); + } + else { + if( sign ) MOVSX32M8toR(mmreg, mem); + else MOVZX32M8toR(mmreg, mem); + } +} + +void _eeReadConstMem16(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-2); + assert(0); + } + else { + if( sign ) MOVSX32M16toR(mmreg, mem); + else MOVZX32M16toR(mmreg, mem); + } +} + +void _eeReadConstMem32(int mmreg, u32 mem) +{ + if( IS_XMMREG(mmreg) ) SSEX_MOVD_M32_to_XMM(mmreg&0xf, mem); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem); + } + else MOV32MtoR(mmreg, mem); +} + +void _eeReadConstMem128(int mmreg, u32 mem) +{ + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQMtoR((mmreg>>4)&0xf, mem+8); + MOVQMtoR(mmreg&0xf, mem); + } + else SSEX_MOVDQA_M128_to_XMM( mmreg&0xf, mem); +} + +void _eeWriteConstMem8(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_CONSTREG(mmreg) ) MOV8ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV8ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV8RtoM(mem, mmreg); +} + +void _eeWriteConstMem16(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_CONSTREG(mmreg) ) MOV16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV16RtoM(mem, mmreg); +} + +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + switch(op) { + case 0: // and + if( IS_CONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else AND16RtoM(mem, mmreg); + break; + case 1: // and + if( IS_CONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else OR16RtoM(mem, mmreg); + break; + default: assert(0); + } +} + +void _eeWriteConstMem32(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV32RtoM(mem, mmreg); +} + +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op) +{ + switch(op) { + case 0: // and + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_PAND_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PANDMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + AND32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + AND32RtoM(mem, mmreg&0xf); + } + break; + + case 1: // or + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_POR_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PORMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + OR32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + OR32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + OR32RtoM(mem, mmreg&0xf); + } + break; + + case 2: // not and + if( mmreg & MEM_XMMTAG ) { + _deleteEEreg(mmreg>>16, 1); + SSEX_PANDN_M128_to_XMM(mmreg&0xf, mem); + SSEX_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( mmreg & MEM_MMXTAG ) { + _deleteEEreg(mmreg>>16, 1); + PANDNMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + NOT32R(mmreg&0xf); + AND32RtoM(mem, mmreg&0xf); + } + break; + + default: assert(0); + } +} + +void _eeWriteConstMem64(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_XMM_to_M64(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + } + else assert(0); +} + +void _eeWriteConstMem128(u32 mem, int mmreg) +{ + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + MOVQRtoM(mem+8, (mmreg>>4)&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + SetMMXstate(); + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + MOVQRtoM(mem+8, mmreg&0xf); + } + else SSEX_MOVDQA_XMM_to_M128(mem, mmreg&0xf); +} + +void _eeMoveMMREGtoR(x86IntRegType to, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_R(to, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVD32MMXtoR(to, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) MOV32ItoR(to, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoR(to, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else if( mmreg != to ) MOV32RtoR(to, mmreg); +} + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: return psxHw4ConstRead8(x86reg, mem, sign); + case 0x1000: return hwConstRead8(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead8(x86reg, mem, sign); + case 0x1200: return gsConstRead8(x86reg, mem, sign); + case 0x1400: + { + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + return 1; + } + + default: + _eeReadConstMem8(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +u16 recMemRead16() { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( mem>>16 ) { + case 0x1000: return hwRead16(mem); + case 0x1f80: return psxHwRead16(mem); + case 0x1200: return *(u16*)(PS2MEM_BASE+(mem&~0xc00)); + case 0x1800: return 0; + case 0x1a00: return ba0R16(mem); + case 0x1f90: + case 0x1f00: + return SPU2read(mem); + case 0x1400: + { + u32 ret = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u16*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: return hwConstRead16(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead16(x86reg, mem, sign); + case 0x1200: return gsConstRead16(x86reg, mem, sign); + case 0x1800: + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + case 0x1a00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)ba0R16); + ADD32ItoR(ESP, 4); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f90: + case 0x1f00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1400: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + default: + _eeReadConstMem16(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +__declspec(naked) +u32 recMemRead32() { + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwread + cmp dx, 0x1f80 + je psxhwread + cmp dx, 0x1200 + je gsread + cmp dx, 0x1400 + je devread + + // default read + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +hwread: + { + __asm { + cmp ecx, 0x10002000 + jb counterread + + cmp ecx, 0x1000f260 + je hwsifpresetread + cmp ecx, 0x1000f240 + je hwsifsyncread + + cmp ecx, 0x10003000 + jb hwdefread2 + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + + // ipu +hwdefread2: + push ecx + call ipuRead32 + add esp, 4 + ret + + // sif +hwsifpresetread: + mov eax, 0 + ret +hwsifsyncread: + mov eax, dword ptr [0x1000F240+PS2MEM_BASE_] + or eax, 0xF0000102 + ret + } + +counterread: + { + static u32 mem, index; + + // counters + __asm mov mem, ecx + index = (mem>>11)&3; + + if( (mem&0x7ff) == 0 ) { + __asm { + push index + call rcntRcount + add esp, 4 + and eax, 0xffff + ret + } + } + + index = (u32)&counters[index] + ((mem>>2)&0xc); + + __asm { + mov eax, index + mov eax, dword ptr [eax] + movzx eax, ax + ret + } + } + } + +psxhwread: + __asm { + push ecx + call psxHwRead32 + add esp, 4 + ret + } + +gsread: + __asm { + and ecx, 0xfffff3ff + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +devread: + __asm { + and ecx, 0xfbffffff + push ecx + call DEV9read32 + add esp, 4 + ret + } +} + +int recMemConstRead32(u32 x86reg, u32 mem) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&~0xffff) ) { + case 0x10000000: return hwConstRead32(x86reg, mem); + case 0x1f800000: return psxHwConstRead32(x86reg, mem); + case 0x12000000: return gsConstRead32(x86reg, mem); + case 0x14000000: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read32); + return 1; + + default: + _eeReadConstMem32(x86reg, VM_RETRANSLATE(mem)); + return 0; + } +} + +void recMemRead64(u64 *out) +{ + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: *out = hwRead64(mem); return; + case 0x11000000: *out = *(u64*)(PS2MEM_BASE+mem); return; + case 0x12000000: *out = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); return; + + default: + //assert(0); + *out = *(u64*)(PS2MEM_BASE+mem); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead64(mem, mmreg); return; + case 0x12000000: gsConstRead64(mem, mmreg); return; + default: + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, VM_RETRANSLATE(mem)); + else { + MOVQMtoR(mmreg, VM_RETRANSLATE(mem)); + SetMMXstate(); + } + return; + } +} + +void recMemRead128(u64 *out) { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: + hwRead128(mem, out); + return; + case 0x12000000: + out[0] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); + out[1] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)+8); + return; + case 0x11000000: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + default: + //assert(0); + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead128(u32 mem, int xmmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead128(mem, xmmreg); return; + case 0x12000000: gsConstRead128(mem, xmmreg); return; + default: + _eeReadConstMem128(xmmreg, VM_RETRANSLATE(mem)); + return; + } +} + +void errwrite() +{ + int i, bit, tempeax; + __asm mov i, ecx + __asm mov tempeax, eax + __asm mov bit, edx + SysPrintf("Error write%d at %x\n", bit, i); + assert(0); + __asm mov eax, tempeax + __asm mov ecx, i +} + +void recMemWrite8() +{ + register u32 mem; + register u8 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, al + + switch( mem>>16 ) { + case 0x1f40: psxHw4Write8(mem, value); return; + case 0x1000: hwWrite8(mem, value); return; + case 0x1f80: psxHwWrite8(mem, value); return; + case 0x1200: gsWrite8(mem, value); return; + case 0x1400: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + CHECK_GSMEM(mem); + *(u8*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite8(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: psxHw4ConstWrite8(mem, mmreg); return 0; + case 0x1000: hwConstWrite8(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite8(mem, mmreg); return 0; + case 0x1200: gsConstWrite8(mem, mmreg); return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write8); + return 0; + + case 0x1100: + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +void recMemWrite16() { + + register u32 mem; + register u16 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, ax + + switch( mem>>16 ) { + case 0x1000: hwWrite16(mem, value); return; + case 0x1f80: psxHwWrite16(mem, value); return; + case 0x1200: gsWrite16(mem, value); return; + case 0x1f90: + case 0x1f00: SPU2write(mem, value); return; + case 0x1400: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + CHECK_GSMEM(mem); + *(u16*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite16(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: hwConstWrite16(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite16(mem, mmreg); return 0; + case 0x1200: gsConstWrite16(mem, mmreg); return 0; + case 0x1f90: + case 0x1f00: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write16); + return 0; + + case 0x1100: + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +__declspec(naked) +void recMemWrite32() +{ + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1f80 + je psxwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1400 + je devwrite + cmp dx, 0x1100 + je vuwrite + } + + CHECK_GSMEM_ASM(); + + __asm { + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + ret + +hwwrite: + push eax + push ecx + call hwWrite32 + add esp, 8 + ret +psxwrite: + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret +gswrite: + push eax + push ecx + call gsWrite32 + add esp, 8 + ret +devwrite: + and ecx, 0xfbffffff + push eax + push ecx + call DEV9write32 + add esp, 8 + ret +vuwrite: + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite32(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem&0xffff0000 ) { + case 0x10000000: hwConstWrite32(mem, mmreg); return 0; + case 0x1f800000: psxHwConstWrite32(mem, mmreg); return 0; + case 0x12000000: gsConstWrite32(mem, mmreg); return 0; + case 0x1f900000: + case 0x1f000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x14000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1100: + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) void recMemWrite64() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + // default write + mov edx, 64 + call errwrite + +hwwrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call hwWrite64 + add esp, 12 + ret + +gswrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call gsWrite64 + add esp, 12 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem>>16) ) { + case 0x1000: hwConstWrite64(mem, mmreg); return 0; + case 0x1200: gsConstWrite64(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) +void recMemWrite128() +{ + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + mov edx, 128 + call errwrite + +hwwrite: + + push eax + push ecx + call hwWrite128 + add esp, 8 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov edi, dword ptr [eax+8] + mov eax, dword ptr [eax+12] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + mov dword ptr [ecx+PS2MEM_BASE_+8], edi + mov dword ptr [ecx+PS2MEM_BASE_+12], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + + // default write + //movaps xmm7, qword ptr [eax] + + // removes possible exceptions and saves on remapping memory + // *might* be faster for certain games, no way to tell +// cmp ecx, 0x20000000 +// jb Write128 +// +// // look for better mapping +// mov edx, ecx +// shr edx, 12 +// shl edx, 3 +// add edx, memLUT +// mov edx, dword ptr [edx + 4] +// cmp edx, 0 +// je Write128 +// mov edx, dword ptr [edx] +// cmp edx, 0 +// je Write128 +// and ecx, 0xfff +// movaps qword ptr [ecx+edx], xmm7 +// jmp CheckOverwrite +//Write128: + //movaps qword ptr [ecx+PS2MEM_BASE_], xmm7 + ret + +gswrite: + sub esp, 8 + movlps xmm7, qword ptr [eax] + movlps qword ptr [esp], xmm7 + push ecx + call gsWrite64 + + // call again for upper 8 bytes + movlps xmm7, qword ptr [eax+8] + movlps qword ptr [esp+4], xmm7 + add [esp], 8 + call gsWrite64 + add esp, 12 + ret + } +} + +int recMemConstWrite128(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstWrite128(mem, mmreg); return 0; + case 0x12000000: gsConstWrite128(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +int memRead8 (u32 mem, u8 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = psxHw4Read8(mem); return 0; + case 0x10000000: *out = hwRead8(mem); return 0; + case 0x1f800000: *out = psxHwRead8(mem); return 0; + case 0x12000000: *out = gsRead8(mem); return 0; + case 0x14000000: + *out = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (s8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (s8)hwRead8(mem); return 0; + case 0x1f800000: *out = (s8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (s8)gsRead8(mem); return 0; + case 0x14000000: + *out = (s8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (u8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (u8)hwRead8(mem); return 0; + case 0x1f800000: *out = (u8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (u8)gsRead8(mem); return 0; + case 0x14000000: + *out = (u8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead16(mem); return 0; + case 0x1f800000: *out = psxHwRead16(mem); return 0; + case 0x12000000: *out = gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = SPU2read(mem); return 0; + break; + case 0x14000000: + *out = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s16)hwRead16(mem); return 0; + case 0x1f800000: *out = (s16)psxHwRead16(mem); return 0; + case 0x12000000: *out = (s16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (s16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (s16)SPU2read(mem); return 0; + break; + case 0x14000000: + *out = (s16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u16)hwRead16(mem ); return 0; + case 0x1f800000: *out = (u16)psxHwRead16(mem ); return 0; + case 0x12000000: *out = (u16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (u16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (u16)SPU2read(mem ); return 0; + break; + case 0x14000000: + *out = (u16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead32(mem); return 0; + case 0x1f800000: *out = psxHwRead32(mem); return 0; + case 0x12000000: *out = gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s32)hwRead32(mem); return 0; + case 0x1f800000: *out = (s32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (s32)gsRead32(mem); return 0; + case 0x14000000: + *out = (s32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u32)hwRead32(mem); return 0; + case 0x1f800000: *out = (u32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (u32)gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead64(mem); return 0; + case 0x12000000: *out = gsRead64(mem); return 0; + + default: + *out = *(u64*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: + hwRead128(mem, out); + return 0; + case 0x12000000: + out[0] = gsRead64(mem); + out[1] = gsRead64(mem + 8); + return 0; + + default: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: psxHw4Write8(mem, value); return; + case 0x10000000: hwWrite8(mem, value); return; + case 0x1f800000: psxHwWrite8(mem, value); return; + case 0x12000000: gsWrite8(mem, value); return; + case 0x14000000: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + + default: + CHECK_GSMEM(mem); + + *(u8*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite16(mem, value); return; + case 0x1f800000: psxHwWrite16(mem, value); return; + case 0x12000000: gsWrite16(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + + default: + CHECK_GSMEM(mem); + + *(u16*)(PS2MEM_BASE+mem) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite32(mem, value); return; + case 0x1f800000: psxHwWrite32(mem, value); return; + case 0x12000000: gsWrite32(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write32(mem & ~0x4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0x4000000, value); + return; + + default: + CHECK_GSMEM(mem); + *(u32*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite64(mem, value); return; + case 0x12000000: gsWrite64(mem, value); return; + + default: + CHECK_GSMEM(mem); + *(u64*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite128(mem, value); return; + case 0x12000000: + gsWrite64(mem, value[0]); + gsWrite64(mem + 8, value[1]); + return; + + default: + + CHECK_GSMEM(mem); + + *(u64*)(PS2MEM_BASE+mem) = value[0]; + *(u64*)(PS2MEM_BASE+mem+8) = value[1]; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +#else + +u8 *psM; //32mb Main Ram +u8 *psR; //4mb rom area +u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +u8 *psR2; // 0x00080000 +u8 *psER; // 0x001C0000 +u8 *psS; //0.015 mb, scratch pad + +uptr *memLUTR; +uptr *memLUTW; +uptr *memLUTRK; +uptr *memLUTWK; +uptr *memLUTRU; +uptr *memLUTWU; + +///////////////////////////// +// REGULAR MEM START +///////////////////////////// + +void memMapMem(u32 base) { + int i; + + for (i=0; i<0x02000; i++) memLUTRK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTRK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTRK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTRK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTRK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTRK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x02000; i++) memLUTWK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTWK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTWK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTWK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTWK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTWK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x00010; i++) memLUTRK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x18000 + base] = 4; // b80 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f000 + base] = 8; // spu2 (not sure) + + for (i=0; i<0x00010; i++) memLUTWK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f000 + base] = 8; // spu2 (not sure) +} + +void memMapKernelMem() { + memMapMem(0xa0000); + memMapMem(0x80000); + memMapMem(0x00000); +} + +void memMapSupervisorMem() { +} + +void memMapUserMem() { +} + +int memInit() { + int i; + + memLUTRK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTRU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + + psM = (char*)_aligned_malloc(0x02000010, 16); + psR = (char*)_aligned_malloc(0x00400010, 16); + psR1 = (char*)_aligned_malloc(0x00080010, 16); + psR2 = (char*)_aligned_malloc(0x00080010, 16); + psER = (char*)_aligned_malloc(0x001C0010, 16); + psS = (char*)_aligned_malloc(0x00004010, 16); + if (memLUTRK == NULL || memLUTWK == NULL || + memLUTRU == NULL || memLUTWU == NULL || + psM == NULL || psR == NULL || psR1 == NULL || + psR2 == NULL || psER == NULL || psS == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(memLUTRK, 0, 0x100000 * 4); + memset(memLUTWK, 0, 0x100000 * 4); + memset(memLUTRU, 0, 0x100000 * 4); + memset(memLUTWU, 0, 0x100000 * 4); + + memset(psM, 0, 0x02000010); + memset(psR, 0, 0x00400010); + memset(psR1, 0, 0x00080010); + memset(psR2, 0, 0x00080010); + memset(psER, 0, 0x001C0010); + memset(psS, 0, 0x00004010); + + if (psxInit() == -1) return -1; + + for (i=0x00000; i<0x00004; i++) memLUTRK[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWK[i + 0x70000] = (uptr)&psS[i << 12]; + + for (i=0x00000; i<0x00004; i++) memLUTRU[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWU[i + 0x70000] = (uptr)&psS[i << 12]; + + + memMapKernelMem(); + memMapSupervisorMem(); + memMapUserMem(); + + memSetKernelMode(); + + return 0; +} + +void memShutdown() { + FREE(psM); + FREE(psR); + FREE(psR1); + FREE(psR2); + FREE(psER); + FREE(psS); + FREE(memLUTRK); + FREE(memLUTWK); + FREE(memLUTRU); + FREE(memLUTWU); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { +// SysPrintf("memSetPageAddr: %8.8x -> %8.8x\n", vaddr, paddr); + + memLUTRU[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWU[vaddr >> 12] = memLUTWK[paddr >> 12]; + + memLUTRK[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWK[vaddr >> 12] = memLUTWK[paddr >> 12]; +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + memLUTRU[vaddr >> 12] = 0; + memLUTWU[vaddr >> 12] = 0; + +#ifdef FULLTLB + memLUTRK[vaddr >> 12] = 0; + memLUTWK[vaddr >> 12] = 0; +#endif +} + +int memRead8 (u32 mem, u8 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (s8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (u8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = ba0R16(mem); return 0; + case 6: // gsm + *out = gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (s16)ba0R16(mem); return 0; + case 6: // gsm + *out = (s16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (s16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (u16)ba0R16(mem); return 0; + case 6: // gsm + *out = (u16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (u16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + assert( (int)p < 8 ); + + switch ((int)p) { + case 1: // hwm + *out = hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u64*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u64*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead64(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead64(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read64 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u64 *tmp = (u64*)readCache(mem); + out[0] = tmp[0]; + out[1] = tmp[1]; + return 0; + } +#endif + p+= mem & 0xfff; + out[0] = ((u64*)p)[0]; + out[1] = ((u64*)p)[1]; + return 0; + } + + switch ((int)p) { + case 1: // hwm + hwRead128(mem & ~0xa0000000, out); return 0; + case 6: // gsm + out[0] = gsRead64((mem ) & ~0xa0000000); + out[1] = gsRead64((mem+8) & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read128 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache8(mem, value); + return; + } +#endif + *(u8 *)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&(~3)); +// PSXREC_CLEARM(mem & 0x1ffffc); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite8(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite8(mem & ~0xa0000000, value); return; + case 3: // psh4 + psxHw4Write8(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite8(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write8(mem & ~0xa4000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, value); + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache16(mem, value); + return; + } +#endif + *(u16*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~1); + //PSXREC_CLEARM(mem & 0x1ffffe); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite16(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite16(mem & ~0xa0000000, value); return; + case 5: // ba0 +#ifdef MEM_LOG + MEM_LOG("ba00000 Memory write16 to address %x with data %x\n", mem, value); +#endif + return; + case 6: // gsm + gsWrite16(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write16(mem & ~0xa4000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, value); + return; + case 8: // spu2 + SPU2write(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + char *p; + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache32(mem, value); + return; + } +#endif + *(u32*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); +// PSXREC_CLEARM(mem & 0x1fffff); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite32(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite32(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite32(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write32(mem & ~0xa4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, value); + return; + } +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { + #ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache64(mem, value); + return; + } + #endif + /* __asm __volatile ( + "movq %1, %%mm0\n" + "movq %%mm0, %0\n" + "emms\n" + : "=m"(*(u64*)(p + (mem & 0xfff))) : "m"(value) + );*/ + *(u64*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + + + switch ((int)p) { + case 1: // hwm + hwWrite64(mem & ~0xa0000000, value); + return; + case 6: // gsm + gsWrite64(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache128(mem, value); + return; + } +#endif + p+= mem & 0xfff; + ((u64*)p)[0] = value[0]; + ((u64*)p)[1] = value[1]; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + +/* PSXREC_CLEARM((mem) & 0x1fffff); + PSXREC_CLEARM((mem+4) & 0x1fffff); + PSXREC_CLEARM((mem+8) & 0x1fffff); + PSXREC_CLEARM((mem+12) & 0x1fffff);*/ + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite128(mem & ~0xa0000000, value); + return; + case 6: // gsm + mem &= ~0xa0000000; + gsWrite64(mem, value[0]); + gsWrite64(mem+8, value[1]); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + + +#endif // WIN32_VIRTUAL_MEM + +void loadBiosRom(char *ext, u8 *dest) { + struct stat buf; + char Bios1[256]; + char Bios[256]; + FILE *fp; + char *ptr; + int i; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + sprintf(Bios1, "%s.%s", Bios, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s", Bios); + ptr = Bios1; i = strlen(Bios1); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = 0; + strcat(Bios1, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s%s.bin", Config.BiosDir, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + SysPrintf("\n\n\n"); + SysPrintf("**************\n"); + SysPrintf("%s NOT FOUND\n", ext); + SysPrintf("**************\n\n\n"); +} + +void memReset() { + struct stat buf; + char Bios[256]; + FILE *fp; + +#ifdef WIN32_VIRTUAL_MEM + DWORD OldProtect; + memset(PS2MEM_BASE, 0, 0x02000000); + memset(PS2MEM_SCRATCH, 0, 0x00004000); +#else + memset(psM, 0, 0x02000000); + memset(psS, 0, 0x00004000); +#endif + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + if (stat(Bios, &buf) == -1) { + SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios); + return; + } + +#ifdef WIN32_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + fp = fopen(Bios, "rb"); + fread(PS2MEM_ROM, 1, buf.st_size, fp); + fclose(fp); + + BiosVersion = GetBiosVersion(); + SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff); + + //injectIRX("host.irx"); //not fully tested; still buggy + + // reset memLUT + + loadBiosRom("rom1", PS2MEM_ROM1); + loadBiosRom("rom2", PS2MEM_ROM2); + loadBiosRom("erom", PS2MEM_EROM); + +#ifdef WIN32_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif +} + +void memSetKernelMode() { +#ifndef WIN32_VIRTUAL_MEM + memLUTR = memLUTRK; + memLUTW = memLUTWK; +#endif + MemMode = 0; +} + +void memSetSupervisorMode() { +} + +void memSetUserMode() { +#ifdef FULLTLB +#ifndef WIN32_VIRTUAL_MEM + memLUTR = memLUTRU; + memLUTW = memLUTWU; +#endif + MemMode = 2; +#endif +} diff --git a/Memory.h b/Memory.h new file mode 100644 index 0000000000..36ed71f58d --- /dev/null +++ b/Memory.h @@ -0,0 +1,263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +////////// +// Rewritten by zerofrog to add os virtual memory +////////// + +#ifndef __MEMORY_H__ +#define __MEMORY_H__ + +//#define ENABLECACHE + +#ifdef WIN32_VIRTUAL_MEM + +typedef struct _PSMEMORYMAP +{ + ULONG_PTR* aPFNs, *aVFNs; +} PSMEMORYMAP; + +#define TRANSFORM_ADDR(memaddr) ( ((u32)(memaddr)>=0x40000000) ? ((memaddr)&~0xa0000000) : (memaddr) ) + +//new memory model +#define PS2MEM_BASE_ 0x18000000 +#define PS2MEM_PSX_ (PS2MEM_BASE_+0x1c000000) + +#define PS2MEM_BASE ((u8*)PS2MEM_BASE_) +#define PS2MEM_HW ((u8*)((u32)PS2MEM_BASE+0x10000000)) +#define PS2MEM_ROM ((u8*)((u32)PS2MEM_BASE+0x1fc00000)) +#define PS2MEM_ROM1 ((u8*)((u32)PS2MEM_BASE+0x1e000000)) +#define PS2MEM_ROM2 ((u8*)((u32)PS2MEM_BASE+0x1e400000)) +#define PS2MEM_EROM ((u8*)((u32)PS2MEM_BASE+0x1e040000)) +#define PS2MEM_PSX ((u8*)PS2MEM_PSX_) +#define PS2MEM_SCRATCH ((u8*)((u32)PS2MEM_BASE+0x50000000)) +#define PS2MEM_VU0MICRO ((u8*)((u32)PS2MEM_BASE+0x11000000)) +#define PS2MEM_VU0MEM ((u8*)((u32)PS2MEM_BASE+0x11004000)) +#define PS2MEM_VU1MICRO ((u8*)((u32)PS2MEM_BASE+0x11008000)) +#define PS2MEM_VU1MEM ((u8*)((u32)PS2MEM_BASE+0x1100c000)) + +// function for mapping memory +#define PS2MEM_PSXHW ((u8*)((u32)PS2MEM_BASE+0x1f800000)) +#define PS2MEM_PSXHW4 ((u8*)((u32)PS2MEM_BASE+0x1f400000)) +#define PS2MEM_GS ((u8*)((u32)PS2MEM_BASE+0x12000000)) +#define PS2MEM_DEV9 ((u8*)((u32)PS2MEM_BASE+0x14000000)) +#define PS2MEM_SPU2 ((u8*)((u32)PS2MEM_BASE+0x1f900000)) +#define PS2MEM_SPU2_ ((u8*)((u32)PS2MEM_BASE+0x1f000000)) // ? +#define PS2MEM_B80 ((u8*)((u32)PS2MEM_BASE+0x18000000)) +#define PS2MEM_BA0 ((u8*)((u32)PS2MEM_BASE+0x1a000000)) + +#define PSM(mem) (PS2MEM_BASE + TRANSFORM_ADDR(mem)) + +#else + +extern u8 *psM; //32mb Main Ram +extern u8 *psR; //4mb rom area +extern u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +extern u8 *psR2; // 0x00080000 +extern u8 *psER; // 0x001C0000 +extern u8 *psS; //0.015 mb, scratch pad + +#define PS2MEM_BASE psM +#define PS2MEM_HW psH +#define PS2MEM_ROM psR +#define PS2MEM_ROM1 psR1 +#define PS2MEM_ROM2 psR2 +#define PS2MEM_EROM psER +#define PS2MEM_SCRATCH psS + +extern u8 g_RealGSMem[0x2000]; +#define PS2MEM_GS g_RealGSMem + +//#define _PSM(mem) (memLUTR[(mem) >> 12] == 0 ? NULL : (void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define PSM(mem) ((void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define FREE(ptr) _aligned_free(ptr) + +extern uptr *memLUTR; +extern uptr *memLUTW; +extern uptr *memLUTRK; +extern uptr *memLUTWK; +extern uptr *memLUTRU; +extern uptr *memLUTWU; + +#endif + +#define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs16(mem) (*(s16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs32(mem) (*(s32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs64(mem) (*(s64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu8(mem) (*(u8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu16(mem) (*(u16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu32(mem) (*(u32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu64(mem) (*(u64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) + +#define psRs8(mem) (*(s8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs16(mem) (*(s16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs32(mem) (*(s32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs64(mem) (*(s64*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu8(mem) (*(u8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu16(mem) (*(u16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu32(mem) (*(u32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu64(mem) (*(u64*)&PS2MEM_ROM[(mem) & 0x3fffff]) + +#define psR1s8(mem) (*(s8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s16(mem) (*(s16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s32(mem) (*(s32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s64(mem) (*(s64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u8(mem) (*(u8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u16(mem) (*(u16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u32(mem) (*(u32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u64(mem) (*(u64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) + +#define psR2s8(mem) (*(s8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s16(mem) (*(s16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s32(mem) (*(s32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s64(mem) (*(s64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u8(mem) (*(u8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u16(mem) (*(u16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u32(mem) (*(u32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u64(mem) (*(u64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) + +#define psERs8(mem) (*(s8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs16(mem) (*(s16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs32(mem) (*(s32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs64(mem) (*(s64*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu8(mem) (*(u8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu16(mem) (*(u16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff]) + +#define psSs8(mem) (*(s8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs16(mem) (*(s16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs32(mem) (*(s32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs64(mem) (*(s64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu8(mem) (*(u8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu16(mem) (*(u16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) + +#define PSMs8(mem) (*(s8 *)PSM(mem)) +#define PSMs16(mem) (*(s16*)PSM(mem)) +#define PSMs32(mem) (*(s32*)PSM(mem)) +#define PSMs64(mem) (*(s64*)PSM(mem)) +#define PSMu8(mem) (*(u8 *)PSM(mem)) +#define PSMu16(mem) (*(u16*)PSM(mem)) +#define PSMu32(mem) (*(u32*)PSM(mem)) +#define PSMu64(mem) (*(u64*)PSM(mem)) + +int memInit(); +void memReset(); +void memSetKernelMode(); +void memSetSupervisorMode(); +void memSetUserMode(); +void memSetPageAddr(u32 vaddr, u32 paddr); +void memClearPageAddr(u32 vaddr); +void memShutdown(); + +int memRead8(u32 mem, u8 *out); +int memRead8RS(u32 mem, u64 *out); +int memRead8RU(u32 mem, u64 *out); +int memRead16(u32 mem, u16 *out); +int memRead16RS(u32 mem, u64 *out); +int memRead16RU(u32 mem, u64 *out); +int memRead32(u32 mem, u32 *out); +int memRead32RS(u32 mem, u64 *out); +int memRead32RU(u32 mem, u64 *out); +int memRead64(u32 mem, u64 *out); +int memRead128(u32 mem, u64 *out); +void memWrite8 (u32 mem, u8 value); +void memWrite16(u32 mem, u16 value); +void memWrite32(u32 mem, u32 value); +void memWrite64(u32 mem, u64 value); +void memWrite128(u32 mem, u64 *value); + +// recMemConstRead8, recMemConstRead16, recMemConstRead32 return 1 if a call was made, 0 otherwise +u8 recMemRead8(); +u16 recMemRead16(); +u32 recMemRead32(); +void recMemRead64(u64 *out); +void recMemRead128(u64 *out); + +// returns 1 if mem should be cleared +void recMemWrite8(); +void recMemWrite16(); +void recMemWrite32(); +void recMemWrite64(); +void recMemWrite128(); + +// VM only functions +#ifdef WIN32_VIRTUAL_MEM + +void _eeReadConstMem8(int mmreg, u32 mem, int sign); +void _eeReadConstMem16(int mmreg, u32 mem, int sign); +void _eeReadConstMem32(int mmreg, u32 mem); +void _eeReadConstMem128(int mmreg, u32 mem); +void _eeWriteConstMem8(u32 mem, int mmreg); +void _eeWriteConstMem16(u32 mem, int mmreg); +void _eeWriteConstMem32(u32 mem, int mmreg); +void _eeWriteConstMem64(u32 mem, int mmreg); +void _eeWriteConstMem128(u32 mem, int mmreg); +void _eeMoveMMREGtoR(int to, int mmreg); + +// extra ops +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op); +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op); + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead32(u32 x86reg, u32 mem); +void recMemConstRead64(u32 mem, int mmreg); +void recMemConstRead128(u32 mem, int xmmreg); + +int recMemConstWrite8(u32 mem, int mmreg); +int recMemConstWrite16(u32 mem, int mmreg); +int recMemConstWrite32(u32 mem, int mmreg); +int recMemConstWrite64(u32 mem, int mmreg); +int recMemConstWrite128(u32 mem, int xmmreg); + +#else + +#define _eeReadConstMem8 0&& +#define _eeReadConstMem16 0&& +#define _eeReadConstMem32 0&& +#define _eeReadConstMem128 0&& +#define _eeWriteConstMem8 0&& +#define _eeWriteConstMem16 0&& +#define _eeWriteConstMem32 0&& +#define _eeWriteConstMem64 0&& +#define _eeWriteConstMem128 0&& +#define _eeMoveMMREGtoR 0&& + +// extra ops +#define _eeWriteConstMem16OP 0&& +#define _eeWriteConstMem32OP 0&& + +#define recMemConstRead8 0&& +#define recMemConstRead16 0&& +#define recMemConstRead32 0&& +#define recMemConstRead64 0&& +#define recMemConstRead128 0&& + +#define recMemConstWrite8 0&& +#define recMemConstWrite16 0&& +#define recMemConstWrite32 0&& +#define recMemConstWrite64 0&& +#define recMemConstWrite128 0&& + +#endif + +#endif diff --git a/Misc.c b/Misc.c new file mode 100644 index 0000000000..6cc8abce8b --- /dev/null +++ b/Misc.c @@ -0,0 +1,816 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "CDVDisodrv.h" +#include "VUmicro.h" +#ifdef __WIN32__ +#include "RDebug/deci2.h" +#endif + +DWORD dwSaveVersion = 0x7a30000c; +extern u32 s_iLastCOP0Cycle; +extern int g_psxWriteOk; + +PcsxConfig Config; +u32 BiosVersion; +char CdromId[12]; + +char *LabelAuthors = { N_( + "PCSX2 a PS2 emulator\n\n" + "written by:\n" + "saqib, refraction, zerofrog,\n" + "shadow, linuzappz, florin,\n" + "nachbrenner, auMatt, loser, \n" + "alexey silinov, goldfinger,\n" + "\n" + "Webmasters: CKemu, Falcon4ever") +}; + +char *LabelGreets = { N_( + "Greets to: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n" + "Special thanks to: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n" + "Seta-San, Skarmeth, blackd_wd, _Demo_\n" + "\n" + "Credits: Hiryu && Sjeep for their libcdvd (iso parsing and filesystem driver code)\n" + "\n" + "Some betatester/support dudes: Belmont, bositman, ChaosCode, CKemu, crushtest," + "falcon4ever, GeneralPlot, jegHegy, parotaku, Prafull, Razorblade, Rudy_X, Seta-san") +}; + +static struct { + char *name; + u32 size; +} ioprps[]={ + {"IOPRP14", 43845}, + {"IOPRP142", 48109}, + {"IOPRP143", 58317}, + {"IOPRP144", 58525}, + {"IOPRP15", 82741}, + {"IOPRP151", 82917}, + {"IOPRP153", 82949}, + {"IOPRP16", 91909}, + {"IOPRP165", 98901}, + {"IOPRP20", 109809}, + {"IOPRP202", 110993}, + {"IOPRP205", 119797}, + {"IOPRP21", 126857}, + {"IOPRP211", 129577}, + {"IOPRP213", 129577}, + {"IOPRP214", 140945}, + {"IOPRP22", 199257}, + {"IOPRP221", 196937}, + {"IOPRP222", 198233}, + {"IOPRP224", 201065}, + {"IOPRP23", 230329}, + {"IOPRP234", 247641}, + {"IOPRP24", 251065}, + {"IOPRP241", 251049}, + {"IOPRP242", 252409}, + {"IOPRP243", 253201}, + {"IOPRP250", 264897}, + {"IOPRP252", 265233}, + {"IOPRP253", 267217}, + {"IOPRP254", 264449}, + {"IOPRP255", 264449}, + {"IOPRP260", 248945}, + {"IOPRP270", 249121}, + {"IOPRP271", 266817}, + {"IOPRP280", 269889}, + {"IOPRP300", 275345}, + {"DNAS280", 272753}, + {"DNAS270", 251729}, + {"DNAS271", 268977}, + {"DNAS300", 278641}, + {"DNAS280", 272705}, + {"DNAS255", 264945}, + {NULL, 0} +}; + +void GetRPCVersion(char *ioprp, char *rpcver){ + char *p=ioprp; int i; + struct TocEntry te; + + if (p && (CDVD_findfile(p+strlen("cdromN:"), &te) != -1)){ + for (i=0; ioprps[i].size>0; i++) + if (te.fileSize==ioprps[i].size) + break; + if (ioprps[i].size>0) + p=ioprps[i].name; + } + if (p && (p=strstr(p, "IOPRP")+strlen("IOPRP"))){ + for (i=0;(i<4) && p && (*p>='0') && (*p<='9');i++, p++) rpcver[i]=*p; + for ( ; i<4 ;i++ ) rpcver[i]='0'; + } +} + +u32 GetBiosVersion() { + unsigned int fileOffset=0; + char *ROMVER; + char vermaj[8]; + char vermin[8]; + struct romdir *rd; + u32 version; + int i; + + for (i=0; i<512*1024; i++) { + rd = (struct romdir*)&psRu8(i); + if (strncmp(rd->fileName, "RESET", 5) == 0) + break; /* found romdir */ + } + if (i == 512*1024) return -1; + + while(strlen(rd->fileName) > 0){ + if (strcmp(rd->fileName, "ROMVER") == 0){ // found romver + ROMVER = &psRu8(fileOffset); + + strncpy(vermaj, ROMVER+ 0, 2); vermaj[2] = 0; + strncpy(vermin, ROMVER+ 2, 2); vermin[2] = 0; + version = strtol(vermaj, (char**)NULL, 0) << 8; + version|= strtol(vermin, (char**)NULL, 0); + + return version; + } + + if ((rd->fileSize % 0x10)==0) + fileOffset += rd->fileSize; + else + fileOffset += (rd->fileSize + 0x10) & 0xfffffff0; + + rd++; + } + + return -1; +} + +//2002-09-22 (Florin) +int IsBIOS(char *filename, char *description){ + struct stat buf; + char Bios[260], ROMVER[14+1], zone[12+1]; + FILE *fp; + unsigned int fileOffset=0, found=FALSE; + struct romdir rd; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, filename); + + if (stat(Bios, &buf) == -1) return FALSE; + + fp = fopen(Bios, "rb"); + if (fp == NULL) return FALSE; + + while ((ftell(fp)<512*1024) && (fread(&rd, DIRENTRY_SIZE, 1, fp)==1)) + if (strcmp(rd.fileName, "RESET") == 0) + break; /* found romdir */ + + if ((strcmp(rd.fileName, "RESET") != 0) || (rd.fileSize == 0)) { + fclose(fp); + return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img + } + + while(strlen(rd.fileName) > 0){ + if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver + unsigned int filepos=ftell(fp); + fseek(fp, fileOffset, SEEK_SET); + if (fread(&ROMVER, 14, 1, fp) == 0) break; + fseek(fp, filepos, SEEK_SET);//go back + + switch(ROMVER[4]){ + case 'T':sprintf(zone, "T10K "); break; + case 'X':sprintf(zone, "Test ");break; + case 'J':sprintf(zone, "Japan "); break; + case 'A':sprintf(zone, "USA "); break; + case 'E':sprintf(zone, "Europe"); break; + case 'H':sprintf(zone, "HK "); break; + case 'P':sprintf(zone, "Free "); break; + case 'C':sprintf(zone, "China "); break; + default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show + } + sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone, + ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":""); + strncpy(description+ 8, ROMVER+ 0, 2);//ver major + strncpy(description+11, ROMVER+ 2, 2);//ver minor + strncpy(description+14, ROMVER+12, 2);//day + strncpy(description+17, ROMVER+10, 2);//month + strncpy(description+20, ROMVER+ 6, 4);//year + found = TRUE; + } + + if ((rd.fileSize % 0x10)==0) + fileOffset += rd.fileSize; + else + fileOffset += (rd.fileSize + 0x10) & 0xfffffff0; + + if (fread(&rd, DIRENTRY_SIZE, 1, fp)==0) break; + } + fileOffset-=((rd.fileSize + 0x10) & 0xfffffff0) - rd.fileSize; + + fclose(fp); + + if (found) { + char percent[6]; + + if (buf.st_size<(int)fileOffset){ + sprintf(percent, " %d%%", buf.st_size*100/(int)fileOffset); + strcat(description, percent);//we force users to have correct bioses, + //not that lame scph10000 of 513KB ;-) + } + return TRUE; + } + + return FALSE; //fail quietly +} + +// LOAD STUFF + +#define ISODCL(from, to) (to - from + 1) + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [1]; +}; + +#define READTRACK(lsn) \ + if (CDVDreadTrack(lsn, CDVD_MODE_2352) == -1) return -1; \ + buf = CDVDgetBuffer(); if (buf == NULL) return -1; + +int LoadCdrom() { + return 0; +} + +int CheckCdrom() { + u8 *buf; + + READTRACK(16); + strncpy(CdromId, buf+52, 10); + + return 0; +} + +int GetPS2ElfName(char *name){ + FILE *fp; + int f; + char buffer[256];//if a file is longer...it should be shorter :D + char *pos; + static struct TocEntry tocEntry; + int i; + + CDVDFS_init(); + + // check if the file exists + if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){ + SysPrintf("SYSTEM.CNF not found\n"); + return 0;//could not find; not a PS/PS2 cdvd + } + + f=CDVDFS_open("SYSTEM.CNF;1", 1); + CDVDFS_read(f, buffer, 256); + CDVDFS_close(f); + + buffer[tocEntry.fileSize]='\0'; + +// SysPrintf( +// "---------------------SYSTEM.CNF---------------------\n" +// "%s" +// "----------------------------------------------------\n", buffer); + pos=strstr(buffer, "BOOT2"); + if (pos==NULL){ + pos=strstr(buffer, "BOOT"); + if (pos==NULL) { + SysPrintf("This is not a PS2 game!\n"); + return 0; + } + return 1; + } + pos+=strlen("BOOT2"); + while (pos && *pos && pos<=&buffer[255] + && (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z')) + pos++; + if (!pos || *pos==0) + return 0; + + sscanf(pos, "%s", name); + //SysPrintf("ELF name: '%s'\n", name); + + if (strncmp("cdrom0:\\", name, 8) == 0) { + strncpy(CdromId, name+8, 11); CdromId[11] = 0; + } + +// inifile_read(CdromId); + + fp = fopen("System.map", "r"); + if (fp) { + u32 addr; + + SysPrintf("Loading System.map\n", fp); + while (!feof(fp)) { + fseek(fp, 8, SEEK_CUR); + buffer[0] = '0'; buffer[1] = 'x'; + for (i=2; i<10; i++) buffer[i] = fgetc(fp); buffer[i] = 0; + addr = strtoul(buffer, (char**)NULL, 0); + fseek(fp, 3, SEEK_CUR); + for (i=0; i<256; i++) { + buffer[i] = fgetc(fp); + if (buffer[i] == '\n' || buffer[i] == 0) break; + } + if (buffer[i] == 0) break; + buffer[i] = 0; + + disR5900AddSym(addr, buffer); + } + fclose(fp); + } + + return 2; +} + +/*#define PSX_EXE 1 +#define CPE_EXE 2 +#define COFF_EXE 3 +#define INVALID_EXE 4 + +static int PSXGetFileType(FILE *f) { + unsigned long current; + unsigned long mybuf[2048]; + EXE_HEADER *exe_hdr; + FILHDR *coff_hdr; + + current = ftell(f); + fseek(f,0L,SEEK_SET); + fread(mybuf,2048,1,f); + fseek(f,current,SEEK_SET); + + exe_hdr = (EXE_HEADER *)mybuf; + if (memcmp(exe_hdr->id,"PS-X EXE",8)==0) + return PSX_EXE; + + if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E') + return CPE_EXE; + + coff_hdr = (FILHDR *)mybuf; + if (coff_hdr->f_magic == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +int Load(char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + int type; + + strcpy(CdromId, "SLUS_999.99"); + + tmpFile = fopen(ExePath,"rb"); + if (tmpFile == NULL) { SysMessage("Error opening file: %s", ExePath); return 0; } + + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread((void *)PSXM(tmpHead.t_addr), tmpHead.t_size,1,tmpFile); + fclose(tmpFile); + psxRegs.pc = tmpHead.pc0; + psxRegs.GPR.n.gp = tmpHead.gp0; + psxRegs.GPR.n.sp = tmpHead.s_addr; + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + break; + case CPE_EXE: + SysMessage("Pcsx found that you wanna use a CPE file. CPE files not support yet"); + break; + case COFF_EXE: + SysMessage("Pcsx found that you wanna use a COFF file.COFF files not support yet"); + break; + case INVALID_EXE: + SysMessage("This file is not a psx file"); + break; + } + return 1; +} +*/ + +u16 logProtocol; +u8 logSource; +int connected=0; + +#define SYNC_LOGGING + +void __Log(char *fmt, ...) { +#ifdef EMU_LOG + va_list list; + static char tmp[2024]; //hm, should be enough + + va_start(list, fmt); +#ifdef __WIN32__ + if (connected && logProtocol>=0 && logProtocol<0x10){ + vsprintf(tmp, fmt, list); + sendTTYP(logProtocol, logSource, tmp); + }//else //!!!!! is disabled, so the text goes to ttyp AND log +#endif + { +#ifndef LOG_STDOUT + if (varLog & 0x80000000) { + vsprintf(tmp, fmt, list); + SysPrintf(tmp); + } else if( emuLog != NULL ) { + vfprintf(emuLog, fmt, list); + } +#else //i assume that this will not be used (Florin) + vsprintf(tmp, fmt, list); + SysPrintf(tmp); +#endif + } + va_end(list); +#endif +} + +// STATES + +#define STATE_VERSION "STv6" +const char Pcsx2Header[32] = STATE_VERSION " PCSX2 v" PCSX2_VERSION; + +#define _PS2Esave(type) \ + if (type##freeze(FREEZE_SIZE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + fP.data = malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + \ + if (type##freeze(FREEZE_SAVE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + \ + gzwrite(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + gzwrite(f, fP.data, fP.size); \ + free(fP.data); \ + } + +#define _PS2Eload(type) \ + gzread(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + fP.data = (s8*)malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + gzread(f, fP.data, fP.size); \ + } \ + if (type##freeze(FREEZE_LOAD, &fP) == -1) { \ + if (fP.size) free(fP.data); \ + gzclose(f); \ + return -1; \ + } \ + if (fP.size) free(fP.data); + + +extern void gsWaitGS(); + +extern u32 g_nextBranchCycle, g_psxNextBranchCycle; + +int SaveState(char *file) { + + gzFile f; + freezeData fP; + + gsWaitGS(); + + SysPrintf("SaveState: %s\n", file); + f = gzopen(file, "wb"); + if (f == NULL) return -1; + + gzwrite(f, &dwSaveVersion, 4); + + gzwrite(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzwrite(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzwrite(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzwrite(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + + gzwrite(f, PS2MEM_HW, 0x00010000); // hardware memory + + gzwrite(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs] + gzwrite(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzwrite(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzwrite(f, &EEsCycle, sizeof(EEsCycle)); + gzwrite(f, &EEoCycle, sizeof(EEoCycle)); + gzwrite(f, &IOPoCycle, sizeof(IOPoCycle)); + gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + //gzwrite(f, (void*)&ipuRegs, sizeof(IPUregisters)); // ipu regs + //hope didn't forgot any cpu.... + + rcntFreeze(f, 1); + gsFreeze(f, 1); + vu0Freeze(f, 1); + vu1Freeze(f, 1); + vif0Freeze(f, 1); + vif1Freeze(f, 1); + sifFreeze(f, 1); + ipuFreeze(f, 1); + + // iop now + gzwrite(f, psxM, 0x00200000); // 2 MB main memory + //gzwrite(f, psxP, 0x00010000); // pralell memory + gzwrite(f, psxH, 0x00010000); // hardware memory + //gzwrite(f, psxS, 0x00010000); // sif memory + + sioFreeze(f, 1); + cdrFreeze(f, 1); + cdvdFreeze(f, 1); + psxRcntFreeze(f, 1); + //mdecFreeze(f, 1); + sio2Freeze(f, 1); + + SysPrintf("Saving GS\n"); + _PS2Esave(GS); + SysPrintf("Saving SPU2\n"); + _PS2Esave(SPU2); + SysPrintf("Saving DEV9\n"); + _PS2Esave(DEV9); + SysPrintf("Saving USB\n"); + _PS2Esave(USB); + SysPrintf("Saving ok\n"); + + gzclose(f); + + return 0; +} + +extern u32 dumplog; +extern u32 s_vucount; + +int LoadState(char *file) { + + gzFile f; + freezeData fP; + int i; + DWORD OldProtect; + DWORD dwVer; + +#ifdef _DEBUG + s_vucount = 0; + //dumplog |= 2; +#endif + + SysPrintf("LoadState: %s\n", file); + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, &dwVer, 4); + + if( dwVer != dwSaveVersion ) { + gzclose(f); + MessageBox(NULL, "Save state wrong version", "Error", MB_OK); + return 0; + } + + // stop and reset the system first + gsWaitGS(); + + for (i=0; i<48; i++) ClearTLB(i); + + Cpu->Reset(); + recResetVU0(); + recResetVU1(); + psxCpu->Reset(); + + SysPrintf("Loading memory\n"); + +#ifdef WIN32_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + gzread(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzread(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzread(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzread(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + +#ifdef WIN32_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif + + gzread(f, PS2MEM_HW, 0x00010000); // hardware memory + + SysPrintf("Loading structs\n"); + gzread(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzread(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs + gzread(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzread(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzread(f, &EEsCycle, sizeof(EEsCycle)); + gzread(f, &EEoCycle, sizeof(EEoCycle)); + gzread(f, &IOPoCycle, sizeof(IOPoCycle)); + gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + gzread(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + rcntFreeze(f, 0); + gsFreeze(f, 0); + vu0Freeze(f, 0); + vu1Freeze(f, 0); + vif0Freeze(f, 0); + vif1Freeze(f, 0); + sifFreeze(f, 0); + ipuFreeze(f, 0); + + // iop now + SysPrintf("Loading iop mem\n"); + gzread(f, psxM, 0x00200000); // 2 MB main memory + //gzread(f, psxP, 0x00010000); // pralell memory + gzread(f, psxH, 0x00010000); // hardware memory + //gzread(f, psxS, 0x00010000); // sif memory + + SysPrintf("Loading iop stuff\n"); + sioFreeze(f, 0); + cdrFreeze(f, 0); + cdvdFreeze(f, 0); + psxRcntFreeze(f, 0); + //mdecFreeze(f, 0); + sio2Freeze(f, 0); + + SysPrintf("Loading GS\n"); + _PS2Eload(GS); + SysPrintf("Loading SPU2\n"); + _PS2Eload(SPU2); + SysPrintf("Loading DEV9\n"); + _PS2Eload(DEV9); + SysPrintf("Loading USB\n"); + _PS2Eload(USB); + + SysPrintf("Loading ok\n"); + + gzclose(f); + + //dumplog |= 4; + WriteCP0Status(cpuRegs.CP0.n.Status.val); + for (i=0; i<48; i++) WriteTLB(i); + + return 0; +} + +int CheckState(char *file) { + gzFile f; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, header, 32); + + gzclose(f); + + if (strncmp(STATE_VERSION " PCSX2", header, 10)) return -1; + + return 0; +} + + +typedef struct { + char id[8]; + char name[64]; +} LangDef; + +LangDef sLangs[] = { + { "ar_AR", N_("Arabic") }, + { "bg_BG", N_("Bulgarian") }, + { "ca_CA", N_("Catalan") }, + { "du_DU", N_("Dutch") }, + { "de_DE", N_("German") }, + { "el_EL", N_("Greek") }, + { "en_US", N_("English") }, + { "fr_FR", N_("French") }, + { "hb_HB" , N_("Hebrew") }, + { "hu_HU", N_("Hungarian") }, + { "it_IT", N_("Italian") }, + { "ja_JA", N_("Japanese") }, + { "po_PO", N_("Portuguese") }, + { "pl_PL" , N_("Polish") }, + { "ro_RO", N_("Romanian") }, + { "ru_RU", N_("Russian") }, + { "es_ES", N_("Spanish") }, + { "sh_SH" , N_("S-Chinese") }, + { "tc_TC", N_("T-Chinese") }, + { "tr_TR", N_("Turkish") }, + { "", "" }, +}; + + +char *ParseLang(char *id) { + int i=0; + + while (sLangs[i].id[0] != 0) { + if (!strcmp(id, sLangs[i].id)) + return _(sLangs[i].name); + i++; + } + + return id; +} + +void injectIRX(char *filename){ + struct stat buf; + char path[260], name[260], *p, *q; + struct romdir *rd; + int iROMDIR=-1, iIOPBTCONF=-1, iBLANK=-1, i, filesize; + FILE *fp; + + strcpy(name, filename); + for (i=0; name[i] && name[i]!='.' && i<10; i++) name[i]=toupper(name[i]);name[i]=0; + + //phase 1: find ROMDIR in bios + for (p=PS2MEM_ROM; pq){*((u64*)p)=*((u64*)p-4);*((u64*)p+1)=*((u64*)p-3);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iIOPBTCONF].fileSize+=DIRENTRY_SIZE; + + q=PS2MEM_ROM;for (i=0; i<=iROMDIR; i++) q+=(rd[i].fileSize+0xF)&(~0xF); + while (p >q){*((u64*)p)=*((u64*)p-2);*((u64*)p+1)=*((u64*)p-1);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iROMDIR].fileSize+=DIRENTRY_SIZE; + + //phase 3: add the name to the end of IOPBTCONF + p=PS2MEM_ROM;for (i=0; i +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2DMA4irqCallback(void (*callback)()); +void CALLBACK SPU2DMA7irqCallback(void (*callback)()); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2DMA4irqCallback)(void (*callback)()); +typedef void (CALLBACK* _SPU2DMA7irqCallback)(void (*callback)()); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2DMA4irqCallback SPU2DMA4irqCallback; +_SPU2DMA7irqCallback SPU2DMA7irqCallback; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/PS2Etypes.h b/PS2Etypes.h new file mode 100644 index 0000000000..2700c92fe9 --- /dev/null +++ b/PS2Etypes.h @@ -0,0 +1,47 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/Patch.c b/Patch.c new file mode 100644 index 0000000000..f20d41fb62 --- /dev/null +++ b/Patch.c @@ -0,0 +1,322 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Includes +// +#include +#include + +#include "PsxCommon.h" + +// +// Defines +// +#define MAX_PATCH 1024 + +#define IFIS(x,str) if(!strnicmp(x,str,sizeof(str)-1)) + +#define GETNEXT_PARAM() \ + while ( *param && ( *param != ',' ) ) param++; \ + if ( *param ) param++; \ + while ( *param && ( *param == ' ' ) ) param++; \ + if ( *param == 0 ) { SysPrintf( _( "Not enough params for inicommand\n" ) ); return; } + +// +// Typedefs +// +typedef void (*PATCHTABLEFUNC)( char * text1, char * text2 ); + +typedef struct +{ + char * text; + int code; + PATCHTABLEFUNC func; +} PatchTextTable; + +typedef struct +{ + int type; + int cpu; + int placetopatch; + u32 addr; + u32 data; +} IniPatch; + +// +// Function prototypes +// +void patchFunc_comment( char * text1, char * text2 ); +void patchFunc_gametitle( char * text1, char * text2 ); +void patchFunc_patch( char * text1, char * text2 ); + +void inifile_trim( char * buffer ); + +// +// Variables +// +PatchTextTable commands[] = +{ + { "comment", 1, patchFunc_comment }, + { "gametitle", 2, patchFunc_gametitle }, + { "patch", 3, patchFunc_patch }, + { "", 0, NULL } +}; + +PatchTextTable dataType[] = +{ + { "byte", 1, NULL }, + { "word", 2, NULL }, + { "", 0, NULL } +}; + +PatchTextTable cpuCore[] = +{ + { "EE", 1, NULL }, + { "IOP", 2, NULL }, + { "", 0, NULL } +}; + +IniPatch patch[ MAX_PATCH ]; +int patchnumber; + + +// +// Function Implementations +// + +int PatchTableExecute( char * text1, char * text2, PatchTextTable * Table ) +{ + int i = 0; + + while ( Table[ i ].text[ 0 ] ) + { + if ( !strcmp( Table[ i ].text, text1 ) ) + { + if ( Table[ i ].func ) + { + Table[ i ].func( text1, text2 ); + } + break; + } + i++; + } + + return Table[ i ].code; +} + +void _applypatch(int place, IniPatch *p) { + if (p->placetopatch != place) return; + + if (p->cpu == 1) { //EE + if (p->type == 1) { //byte + memWrite8(p->addr, p->data); + } else + if (p->type == 2) { //word + memWrite32(p->addr, p->data); + } + } else + if (p->cpu == 2) { //IOP + if (p->type == 1) { //byte + psxMemWrite8(p->addr, p->data); + } else + if (p->type == 2) { //word + psxMemWrite32(p->addr, p->data); + } + } +} + +//this is for apply patches directly to memory +void applypatch(int place) { + int i; + + if (place == 0) { + SysPrintf(" patchnumber: %d\n", patchnumber); + } + + for ( i = 0; i < patchnumber; i++ ) { + _applypatch(place, &patch[i]); + } +} + +void patchFunc_comment( char * text1, char * text2 ) +{ + SysPrintf( "comment: %s \n", text2 ); +} + +void patchFunc_gametitle( char * text1, char * text2 ) +{ + char str2[256]; + SysPrintf( "gametitle: %s \n", text2 ); +#ifdef __WIN32__ + sprintf(str2,"Running Game %s",text2); + if (gApp.hConsole) SetConsoleTitle(str2); +#endif +} + +void patchFunc_patch( char * cmd, char * param ) +{ + //patch=placetopatch,cpucore,address,type,data + char * pText; + + if ( patchnumber >= MAX_PATCH ) + { + SysPrintf( "Patch ERROR: Maximum number of patches reached: %s=%s\n", cmd, param ); + return; + } + + pText = strtok( param, "," ); + pText = param; +// inifile_trim( pText ); + + patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].cpu = PatchTableExecute( pText, NULL, cpuCore ); + if ( patch[ patchnumber ].cpu == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%X", &patch[ patchnumber ].addr ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].type = PatchTableExecute( pText, NULL, dataType ); + if ( patch[ patchnumber ].type == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%X", &patch[ patchnumber ].data ); + + patchnumber++; +} + +//this routine is for execute the commands of the ini file +void inifile_command( char * cmd ) +{ + int code; + char command[ 256 ]; + char parameter[ 256 ]; + + // extract param part (after '=') + char * pEqual = strchr( cmd, '=' ); + + if ( ! pEqual ) + { + SysPrintf( "Ini file ERROR: unknow line: %s \n", cmd ); + return; + } + + memset( command, 0, sizeof( command ) ); + memset( parameter, 0, sizeof( parameter ) ); + + strncpy( command, cmd, pEqual - cmd ); + strncpy( parameter, pEqual + 1, sizeof( parameter ) ); + + inifile_trim( command ); + inifile_trim( parameter ); + + code = PatchTableExecute( command, parameter, commands ); +} + +void inifile_trim( char * buffer ) +{ + char * pInit = buffer; + char * pEnd = NULL; + + while ( ( *pInit == ' ' ) || ( *pInit == '\t' ) ) //skip space + { + pInit++; + } + if ( ( pInit[ 0 ] == '/' ) && ( pInit[ 1 ] == '/' ) ) //remove comment + { + buffer[ 0 ] = '\0'; + return; + } + pEnd = pInit + strlen( pInit ) - 1; + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + while ( ( *pEnd == '\r' ) || ( *pEnd == '\n' ) || + ( *pEnd == ' ' ) || ( *pEnd == '\t' ) ) + { + pEnd--; + } + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + memmove( buffer, pInit, pEnd - pInit + 1 ); + buffer[ pEnd - pInit + 1 ] = '\0'; +} + +void inisection_process( FILE * f1 ) +{ + char buffer[ 1024 ]; + while( fgets( buffer, sizeof( buffer ), f1 ) ) + { + inifile_trim( buffer ); + if ( buffer[ 0 ] ) + { + inifile_command( buffer ); + } + } +} + +//this routine is for reading the ini file + +void inifile_read( char * name ) +{ + FILE * f1; + char buffer[ 1024 ]; + + patchnumber = 0; +#ifdef __WIN32__ + sprintf( buffer, "patches\\%s.pnach", name ); +#else + sprintf( buffer, "patches/%s.pnach", name ); +#endif + + f1 = fopen( buffer, "rt" ); + if( !f1 ) + { + SysPrintf( _( "patch file for this game not found. Can't apply any patches\n" ) ); + return; + } + + inisection_process( f1 ); + + fclose( f1 ); +} + +void resetpatch( void ) +{ + patchnumber = 0; +} diff --git a/Patch.h b/Patch.h new file mode 100644 index 0000000000..6ffd2203be --- /dev/null +++ b/Patch.h @@ -0,0 +1,10 @@ +#ifndef __PATCH_H__ +#define __PATCH_H__ + +void applypatch( int place ); +void inifile_read( char * name ); +void inifile_command( char * cmd ); +void resetpatch( void ); + +#endif /* __PATCH_H__ */ + diff --git a/Plugins.c b/Plugins.c new file mode 100644 index 0000000000..cf41c33d76 --- /dev/null +++ b/Plugins.c @@ -0,0 +1,603 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define CheckErr(func) \ + err = SysLibError(); \ + if (err != NULL) { SysMessage (_("%s: Error loading %s: %s"), filename, func, err); return -1; } + +#define LoadSym(dest, src, name, checkerr) \ + dest = (src) SysLoadSym(drv, name); if (checkerr == 1) CheckErr(name); \ + if (checkerr == 2) { err = SysLibError(); if (err != NULL) errval = 1; } + +#define TestPS2Esyms(type) { \ + _PS2EgetLibVersion2 PS2EgetLibVersion2; \ + SysLoadSym(drv, "PS2EgetLibType"); CheckErr("PS2EgetLibType"); \ + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) SysLoadSym(drv, "PS2EgetLibVersion2"); CheckErr("PS2EgetLibVersion2"); \ + SysLoadSym(drv, "PS2EgetLibName"); CheckErr("PS2EgetLibName"); \ + if( ((PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff) != PS2E_##type##_VERSION) { \ + SysMessage (_("Can't load '%s', wrong PS2E version (%x != %x)"), filename, (PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff, PS2E_##type##_VERSION); return -1; \ + } \ +} + +static char *err; +static int errval; + +void *GSplugin; + +void CALLBACK GS_printf(int timeout, char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + SysPrintf(msg); +} + +s32 CALLBACK GS_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK GS_keyEvent(keyEvent *ev) {} +void CALLBACK GS_makeSnapshot(char *path) {} +void CALLBACK GS_irqCallback(void (*callback)()) {} +void CALLBACK GS_configure() {} +void CALLBACK GS_about() {} +long CALLBACK GS_test() { return 0; } + +#define LoadGSsym1(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 1); + +#define LoadGSsym0(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); \ + if (GS##dest == NULL) GS##dest = (_GS##dest) GS_##dest; + +#define LoadGSsymN(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); + +int LoadGSplugin(char *filename) { + void *drv; + + GSplugin = SysLoadLibrary(filename); + if (GSplugin == NULL) { SysMessage (_("Could Not Load GS Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = GSplugin; + TestPS2Esyms(GS); + LoadGSsym1(init, "GSinit"); + LoadGSsym1(shutdown, "GSshutdown"); + LoadGSsym1(open, "GSopen"); + LoadGSsym1(close, "GSclose"); + LoadGSsym1(gifTransfer1, "GSgifTransfer1"); + LoadGSsym1(gifTransfer2, "GSgifTransfer2"); + LoadGSsym1(gifTransfer3, "GSgifTransfer3"); + LoadGSsym1(readFIFO, "GSreadFIFO"); + LoadGSsymN(readFIFO2, "GSreadFIFO2"); // optional + LoadGSsym1(vsync, "GSvsync"); + + LoadGSsym0(keyEvent, "GSkeyEvent"); + LoadGSsymN(changeSaveState, "GSchangeSaveState"); + LoadGSsymN(gifSoftReset, "GSgifSoftReset"); + LoadGSsym0(makeSnapshot, "GSmakeSnapshot"); + LoadGSsym0(irqCallback, "GSirqCallback"); + LoadGSsym0(printf, "GSprintf"); + LoadGSsym1(setBaseMem, "GSsetBaseMem"); + LoadGSsym1(reset, "GSreset"); + LoadGSsym1(writeCSR, "GSwriteCSR"); + LoadGSsymN(makeSnapshot2,"GSmakeSnapshot2"); + LoadGSsymN(getDriverInfo,"GSgetDriverInfo"); +#ifdef __WIN32__ + LoadGSsymN(setWindowInfo,"GSsetWindowInfo"); +#endif + LoadGSsym0(freeze, "GSfreeze"); + LoadGSsym0(configure, "GSconfigure"); + LoadGSsym0(about, "GSabout"); + LoadGSsym0(test, "GStest"); + + return 0; +} + +void *PAD1plugin; + +void CALLBACK PAD1_configure() {} +void CALLBACK PAD1_about() {} +long CALLBACK PAD1_test() { return 0; } + +#define LoadPAD1sym1(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 1); + +#define LoadPAD1sym0(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); \ + if (PAD1##dest == NULL) PAD1##dest = (_PAD##dest) PAD1_##dest; + +#define LoadPAD1symN(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); + +int LoadPAD1plugin(char *filename) { + void *drv; + + PAD1plugin = SysLoadLibrary(filename); + if (PAD1plugin == NULL) { SysMessage (_("Could Not Load PAD1 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD1plugin; + TestPS2Esyms(PAD); + LoadPAD1sym1(init, "PADinit"); + LoadPAD1sym1(shutdown, "PADshutdown"); + LoadPAD1sym1(open, "PADopen"); + LoadPAD1sym1(close, "PADclose"); + LoadPAD1sym1(keyEvent, "PADkeyEvent"); + LoadPAD1sym1(startPoll, "PADstartPoll"); + LoadPAD1sym1(poll, "PADpoll"); + LoadPAD1sym1(query, "PADquery"); + + LoadPAD1symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD1sym0(configure, "PADconfigure"); + LoadPAD1sym0(about, "PADabout"); + LoadPAD1sym0(test, "PADtest"); + + return 0; +} + +void *PAD2plugin; + +void CALLBACK PAD2_configure() {} +void CALLBACK PAD2_about() {} +long CALLBACK PAD2_test() { return 0; } + +#define LoadPAD2sym1(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 1); + +#define LoadPAD2sym0(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); \ + if (PAD2##dest == NULL) PAD2##dest = (_PAD##dest) PAD2_##dest; + +#define LoadPAD2symN(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); + +int LoadPAD2plugin(char *filename) { + void *drv; + + PAD2plugin = SysLoadLibrary(filename); + if (PAD2plugin == NULL) { SysMessage (_("Could Not Load PAD2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD2plugin; + TestPS2Esyms(PAD); + LoadPAD2sym1(init, "PADinit"); + LoadPAD2sym1(shutdown, "PADshutdown"); + LoadPAD2sym1(open, "PADopen"); + LoadPAD2sym1(close, "PADclose"); + LoadPAD2sym1(keyEvent, "PADkeyEvent"); + LoadPAD2sym1(startPoll, "PADstartPoll"); + LoadPAD2sym1(poll, "PADpoll"); + LoadPAD2sym1(query, "PADquery"); + + LoadPAD2symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD2sym0(configure, "PADconfigure"); + LoadPAD2sym0(about, "PADabout"); + LoadPAD2sym0(test, "PADtest"); + + return 0; +} + +void *SPU2plugin; + +s32 CALLBACK SPU2_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK SPU2_configure() {} +void CALLBACK SPU2_about() {} +s32 CALLBACK SPU2_test() { return 0; } + +#define LoadSPU2sym1(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 1); + +#define LoadSPU2sym0(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); \ + if (SPU2##dest == NULL) SPU2##dest = (_SPU2##dest) SPU2_##dest; + +#define LoadSPU2symN(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); + +int LoadSPU2plugin(char *filename) { + void *drv; + + SPU2plugin = SysLoadLibrary(filename); + if (SPU2plugin == NULL) { SysMessage (_("Could Not Load SPU2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = SPU2plugin; + TestPS2Esyms(SPU2); + LoadSPU2sym1(init, "SPU2init"); + LoadSPU2sym1(shutdown, "SPU2shutdown"); + LoadSPU2sym1(open, "SPU2open"); + LoadSPU2sym1(close, "SPU2close"); + LoadSPU2sym1(write, "SPU2write"); + LoadSPU2sym1(read, "SPU2read"); + LoadSPU2sym1(readDMA4Mem, "SPU2readDMA4Mem"); + LoadSPU2sym1(writeDMA4Mem, "SPU2writeDMA4Mem"); + LoadSPU2sym1(interruptDMA4,"SPU2interruptDMA4"); + LoadSPU2sym1(readDMA7Mem, "SPU2readDMA7Mem"); + LoadSPU2sym1(writeDMA7Mem, "SPU2writeDMA7Mem"); + LoadSPU2sym1(interruptDMA7,"SPU2interruptDMA7"); + LoadSPU2sym1(DMA4irqCallback, "SPU2DMA4irqCallback"); + LoadSPU2sym1(DMA7irqCallback, "SPU2DMA7irqCallback"); + LoadSPU2sym1(irqCallback, "SPU2irqCallback"); + + LoadSPU2sym0(freeze, "SPU2freeze"); + LoadSPU2sym0(configure, "SPU2configure"); + LoadSPU2sym0(about, "SPU2about"); + LoadSPU2sym0(test, "SPU2test"); + LoadSPU2symN(async, "SPU2async"); + + return 0; +} + +void *CDVDplugin; + +void CALLBACK CDVD_configure() {} +void CALLBACK CDVD_about() {} +long CALLBACK CDVD_test() { return 0; } + +#define LoadCDVDsym1(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 1); + +#define LoadCDVDsym0(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + if (CDVD##dest == NULL) CDVD##dest = (_CDVD##dest) CDVD_##dest; + +#define LoadCDVDsymN(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + +int LoadCDVDplugin(char *filename) { + void *drv; + + CDVDplugin = SysLoadLibrary(filename); + if (CDVDplugin == NULL) { SysMessage (_("Could Not Load CDVD Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = CDVDplugin; + TestPS2Esyms(CDVD); + LoadCDVDsym1(init, "CDVDinit"); + LoadCDVDsym1(shutdown, "CDVDshutdown"); + LoadCDVDsym1(open, "CDVDopen"); + LoadCDVDsym1(close, "CDVDclose"); + LoadCDVDsym1(readTrack, "CDVDreadTrack"); + LoadCDVDsym1(getBuffer, "CDVDgetBuffer"); + LoadCDVDsym1(readSubQ, "CDVDreadSubQ"); + LoadCDVDsym1(getTN, "CDVDgetTN"); + LoadCDVDsym1(getTD, "CDVDgetTD"); + LoadCDVDsym1(getTOC, "CDVDgetTOC"); + LoadCDVDsym1(getDiskType, "CDVDgetDiskType"); + LoadCDVDsym1(getTrayStatus, "CDVDgetTrayStatus"); + LoadCDVDsym1(ctrlTrayOpen, "CDVDctrlTrayOpen"); + LoadCDVDsym1(ctrlTrayClose, "CDVDctrlTrayClose"); + + LoadCDVDsym0(configure, "CDVDconfigure"); + LoadCDVDsym0(about, "CDVDabout"); + LoadCDVDsym0(test, "CDVDtest"); + LoadCDVDsymN(newDiskCB, "CDVDnewDiskCB"); + + return 0; +} + +void *DEV9plugin; + +s32 CALLBACK DEV9_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK DEV9_configure() {} +void CALLBACK DEV9_about() {} +long CALLBACK DEV9_test() { return 0; } + +#define LoadDEV9sym1(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 1); + +#define LoadDEV9sym0(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 0); \ + if (DEV9##dest == NULL) DEV9##dest = (_DEV9##dest) DEV9_##dest; + +int LoadDEV9plugin(char *filename) { + void *drv; + + DEV9plugin = SysLoadLibrary(filename); + if (DEV9plugin == NULL) { SysMessage (_("Could Not Load DEV9 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = DEV9plugin; + TestPS2Esyms(DEV9); + LoadDEV9sym1(init, "DEV9init"); + LoadDEV9sym1(shutdown, "DEV9shutdown"); + LoadDEV9sym1(open, "DEV9open"); + LoadDEV9sym1(close, "DEV9close"); + LoadDEV9sym1(read8, "DEV9read8"); + LoadDEV9sym1(read16, "DEV9read16"); + LoadDEV9sym1(read32, "DEV9read32"); + LoadDEV9sym1(write8, "DEV9write8"); + LoadDEV9sym1(write16, "DEV9write16"); + LoadDEV9sym1(write32, "DEV9write32"); + LoadDEV9sym1(readDMA8Mem, "DEV9readDMA8Mem"); + LoadDEV9sym1(writeDMA8Mem, "DEV9writeDMA8Mem"); + LoadDEV9sym1(irqCallback, "DEV9irqCallback"); + LoadDEV9sym1(irqHandler, "DEV9irqHandler"); + + LoadDEV9sym0(freeze, "DEV9freeze"); + LoadDEV9sym0(configure, "DEV9configure"); + LoadDEV9sym0(about, "DEV9about"); + LoadDEV9sym0(test, "DEV9test"); + + return 0; +} + +void *USBplugin; + +s32 CALLBACK USB_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK USB_configure() {} +void CALLBACK USB_about() {} +long CALLBACK USB_test() { return 0; } + +#define LoadUSBsym1(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 1); + +#define LoadUSBsym0(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 0); \ + if (USB##dest == NULL) USB##dest = (_USB##dest) USB_##dest; + +int LoadUSBplugin(char *filename) { + void *drv; + + USBplugin = SysLoadLibrary(filename); + if (USBplugin == NULL) { SysMessage (_("Could Not Load USB Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = USBplugin; + TestPS2Esyms(USB); + LoadUSBsym1(init, "USBinit"); + LoadUSBsym1(shutdown, "USBshutdown"); + LoadUSBsym1(open, "USBopen"); + LoadUSBsym1(close, "USBclose"); + LoadUSBsym1(read8, "USBread8"); + LoadUSBsym1(read16, "USBread16"); + LoadUSBsym1(read32, "USBread32"); + LoadUSBsym1(write8, "USBwrite8"); + LoadUSBsym1(write16, "USBwrite16"); + LoadUSBsym1(write32, "USBwrite32"); + LoadUSBsym1(irqCallback, "USBirqCallback"); + LoadUSBsym1(irqHandler, "USBirqHandler"); + LoadUSBsym1(setRAM, "USBsetRAM"); + + LoadUSBsym0(freeze, "USBfreeze"); + LoadUSBsym0(configure, "USBconfigure"); + LoadUSBsym0(about, "USBabout"); + LoadUSBsym0(test, "USBtest"); + + return 0; +} +void *FWplugin; + +s32 CALLBACK FW_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK FW_configure() {} +void CALLBACK FW_about() {} +long CALLBACK FW_test() { return 0; } + +#define LoadFWsym1(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 1); + +#define LoadFWsym0(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 0); \ + if (FW##dest == NULL) FW##dest = (_FW##dest) FW_##dest; + +int LoadFWplugin(char *filename) { + void *drv; + + FWplugin = SysLoadLibrary(filename); + if (FWplugin == NULL) { SysMessage (_("Could Not Load FW Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = FWplugin; + TestPS2Esyms(FW); + LoadFWsym1(init, "FWinit"); + LoadFWsym1(shutdown, "FWshutdown"); + LoadFWsym1(open, "FWopen"); + LoadFWsym1(close, "FWclose"); + LoadFWsym1(read32, "FWread32"); + LoadFWsym1(write32, "FWwrite32"); + LoadFWsym1(irqCallback, "FWirqCallback"); + + LoadFWsym0(freeze, "FWfreeze"); + LoadFWsym0(configure, "FWconfigure"); + LoadFWsym0(about, "FWabout"); + LoadFWsym0(test, "FWtest"); + + return 0; +} +static int loadp=0; + +int InitPlugins() { + int ret; + + if( GSsetBaseMem ) GSsetBaseMem(PS2MEM_GS); + + ret = GSinit(); + if (ret != 0) { SysMessage (_("GSinit error: %d"), ret); return -1; } + ret = PAD1init(1); + if (ret != 0) { SysMessage (_("PAD1init error: %d"), ret); return -1; } + ret = PAD2init(2); + if (ret != 0) { SysMessage (_("PAD2init error: %d"), ret); return -1; } + ret = SPU2init(); + if (ret != 0) { SysMessage (_("SPU2init error: %d"), ret); return -1; } + ret = CDVDinit(); + if (ret != 0) { SysMessage (_("CDVDinit error: %d"), ret); return -1; } + ret = DEV9init(); + if (ret != 0) { SysMessage (_("DEV9init error: %d"), ret); return -1; } + ret = USBinit(); + if (ret != 0) { SysMessage (_("USBinit error: %d"), ret); return -1; } + ret = FWinit(); + if (ret != 0) { SysMessage (_("FWinit error: %d"), ret); return -1; } + return 0; +} + +void ShutdownPlugins() { + GSshutdown(); + PAD1shutdown(); + PAD2shutdown(); + SPU2shutdown(); + CDVDshutdown(); + DEV9shutdown(); + USBshutdown(); + FWshutdown(); +} + +int LoadPlugins() { + char Plugin[256]; + + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.GS); + if (LoadGSplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD1); + if (LoadPAD1plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD2); + if (LoadPAD2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.SPU2); + if (LoadSPU2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.CDVD); + if (LoadCDVDplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.DEV9); + if (LoadDEV9plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.USB); + if (LoadUSBplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.FW); + if (LoadFWplugin(Plugin) == -1) return -1; + if (InitPlugins() == -1) return -1; + + loadp=1; + + return 0; +} + +long pDsp; +static pluginsopened = 0; +extern void spu2DMA4Irq(); +extern void spu2DMA7Irq(); +extern void spu2Irq(); +extern HANDLE g_hGSOpen, g_hGSDone; +int OpenPlugins() { + GSdriverInfo info; + int ret; + + if (loadp == 0) return -1; + + //first we need the data + if (CDVDnewDiskCB) CDVDnewDiskCB(cdvdNewDiskCB); + ret = CDVDopen(); + if (ret != 0) { SysMessage (_("Error Opening CDVD Plugin")); return -1; } + cdvdNewDiskCB(); + + //video + GSirqCallback(gsIrq); + + // make sure only call open once per instance + if( !pluginsopened ) { + if( CHECK_MULTIGS ) { + SetEvent(g_hGSOpen); + WaitForSingleObject(g_hGSDone, INFINITE); + } + else { + ret = GSopen((void *)&pDsp, "PCSX2", 0); + if (ret != 0) { SysMessage (_("Error Opening GS Plugin")); return -1; } + } + } + + //then the user input + if (GSgetDriverInfo) { + GSgetDriverInfo(&info); + if (PAD1gsDriverInfo) PAD1gsDriverInfo(&info); + if (PAD2gsDriverInfo) PAD2gsDriverInfo(&info); + } + ret = PAD1open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD1 Plugin")); return -1; } + ret = PAD2open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD2 Plugin")); return -1; } + + //the sound + SysPrintf("SPU2open\n"); + + SPU2DMA4irqCallback(spu2DMA4Irq); + SPU2DMA7irqCallback(spu2DMA7Irq); + SPU2irqCallback(spu2Irq); + ret = SPU2open((void*)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening SPU2 Plugin")); return -1; } + + //and last the dev9 + DEV9irqCallback(dev9Irq); + dev9Handler = DEV9irqHandler(); + ret = DEV9open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening DEV9 Plugin")); return -1; } + + USBirqCallback(usbIrq); + usbHandler = USBirqHandler(); + USBsetRAM(psxM); + ret = USBopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening USB Plugin")); return -1; } + + FWirqCallback(fwIrq); + ret = FWopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening FW Plugin")); return -1; } + +#ifndef NOSTATS + statsOpen(); // for lack of a better place ;) +#endif + + pluginsopened = 1; + return 0; +} + +extern void gsWaitGS(); + +void ClosePlugins() { +#ifndef NOSTATS + statsClose(); // for lack of a better place ;) +#endif + + gsWaitGS(); + + CDVDclose(); + DEV9close(); + USBclose(); + FWclose(); + SPU2close(); + PAD1close(); + PAD2close(); +} + +void ResetPlugins() { + gsWaitGS(); + + ShutdownPlugins(); + InitPlugins(); +} + +void ReleasePlugins() { + if (loadp == 0) return; + + if (GSplugin == NULL || PAD1plugin == NULL || PAD2plugin == NULL || + SPU2plugin == NULL || CDVDplugin == NULL || DEV9plugin == NULL || + USBplugin == NULL || FWplugin == NULL) return; + + ShutdownPlugins(); + + SysCloseLibrary(GSplugin); GSplugin = NULL; + SysCloseLibrary(PAD1plugin); PAD1plugin = NULL; + SysCloseLibrary(PAD2plugin); PAD2plugin = NULL; + SysCloseLibrary(SPU2plugin); SPU2plugin = NULL; + SysCloseLibrary(CDVDplugin); CDVDplugin = NULL; + SysCloseLibrary(DEV9plugin); DEV9plugin = NULL; + SysCloseLibrary(USBplugin); USBplugin = NULL; + SysCloseLibrary(FWplugin); FWplugin = NULL; + loadp=0; +} diff --git a/Plugins.h b/Plugins.h new file mode 100644 index 0000000000..0f282f293c --- /dev/null +++ b/Plugins.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PLUGINS_H__ +#define __PLUGINS_H__ + +#define PLUGINtypedefs +#define PLUGINfuncs +#include "PS2Edefs.h" + +int LoadPlugins(); +void ReleasePlugins(); +int OpenPlugins(); +void ClosePlugins(); +void ResetPlugins(); + +#endif /* __PLUGINS_H__ */ diff --git a/PsxBios.c b/PsxBios.c new file mode 100644 index 0000000000..2e1495e1f7 --- /dev/null +++ b/PsxBios.c @@ -0,0 +1,300 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "PsxCommon.h" + +char *biosA0n[256] = { +// 0x00 + "open", "lseek", "read", "write", + "close", "ioctl", "exit", "sys_a0_07", + "getc", "putc", "todigit", "atof", + "strtoul", "strtol", "abs", "labs", +// 0x10 + "atoi", "atol", "atob", "setjmp", + "longjmp", "strcat", "strncat", "strcmp", + "strncmp", "strcpy", "strncpy", "strlen", + "index", "rindex", "strchr", "strrchr", +// 0x20 + "strpbrk", "strspn", "strcspn", "strtok", + "strstr", "toupper", "tolower", "bcopy", + "bzero", "bcmp", "memcpy", "memset", + "memmove", "memcmp", "memchr", "rand", +// 0x30 + "srand", "qsort", "strtod", "malloc", + "free", "lsearch", "bsearch", "calloc", + "realloc", "InitHeap", "_exit", "getchar", + "putchar", "gets", "puts", "printf", +// 0x40 + "sys_a0_40", "LoadTest", "Load", "Exec", + "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram", + "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets", + "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f", +// 0x50 + "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53", + "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57", + "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init", + "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open", +// 0x60 + "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile", + "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write", + "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase", + "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f", +// 0x70 + "_bu_init", "_96_init", "_96_remove", "sys_a0_73", + "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77", + "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b", + "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f", +// 0x80 + "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83", + "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87", + "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b", + "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f", +// 0x90 + "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93", + "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide", + "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b", + "SetConf", "GetConf", "sys_a0_9e", "SetMem", +// 0xa0 + "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr", + "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0", + "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info", + "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af", +// 0xb0 + "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3", + "?? sub_function", +}; + +char *biosB0n[256] = { +// 0x00 + "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03", + "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent", + "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent", + "EnableEvent", "DisableEvent", "OpenTh", "CloseTh", +// 0x10 + "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD", + "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption", + "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b", + "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f", +// 0x20 + "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23", + "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27", + "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b", + "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f", +// 0x30 + "sys_b0_30", "sys_b0_31", "open", "lseek", + "read", "write", "close", "ioctl", + "exit", "sys_b0_39", "getc", "putc", + "getchar", "putchar", "gets", "puts", +// 0x40 + "cd", "format", "firstfile", "nextfile", + "rename", "delete", "undelete", "AddDevice", + "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD", + "StopCARD", "sys_b0_4d", "_card_write", "_card_read", +// 0x50 + "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53", + "_get_errno", "_get_error", "GetC0Table", "GetB0Table", + "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD", + "_card_status", "_card_wait", +}; + +char *biosC0n[256] = { +// 0x00 + "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP", + "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler", + "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError", + "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f", +// 0x10 + "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut", + "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc", + "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect", + "PatchAOTable", +}; + +//#define r0 (psxRegs.GPR.n.r0) +#define at (psxRegs.GPR.n.at) +#define v0 (psxRegs.GPR.n.v0) +#define v1 (psxRegs.GPR.n.v1) +#define a0 (psxRegs.GPR.n.a0) +#define a1 (psxRegs.GPR.n.a1) +#define a2 (psxRegs.GPR.n.a2) +#define a3 (psxRegs.GPR.n.a3) +#define t0 (psxRegs.GPR.n.t0) +#define t1 (psxRegs.GPR.n.t1) +#define t2 (psxRegs.GPR.n.t2) +#define t3 (psxRegs.GPR.n.t3) +#define t4 (psxRegs.GPR.n.t4) +#define t5 (psxRegs.GPR.n.t5) +#define t6 (psxRegs.GPR.n.t6) +#define t7 (psxRegs.GPR.n.t7) +#define s0 (psxRegs.GPR.n.s0) +#define s1 (psxRegs.GPR.n.s1) +#define s2 (psxRegs.GPR.n.s2) +#define s3 (psxRegs.GPR.n.s3) +#define s4 (psxRegs.GPR.n.s4) +#define s5 (psxRegs.GPR.n.s5) +#define s6 (psxRegs.GPR.n.s6) +#define s7 (psxRegs.GPR.n.s7) +#define t8 (psxRegs.GPR.n.t6) +#define t9 (psxRegs.GPR.n.t7) +#define k0 (psxRegs.GPR.n.k0) +#define k1 (psxRegs.GPR.n.k1) +#define gp (psxRegs.GPR.n.gp) +#define sp (psxRegs.GPR.n.sp) +#define fp (psxRegs.GPR.n.s8) +#define ra (psxRegs.GPR.n.ra) +#define pc0 (psxRegs.pc) + +#define Ra0 ((char*)PSXM(a0)) +#define Ra1 ((char*)PSXM(a1)) +#define Ra2 ((char*)PSXM(a2)) +#define Ra3 ((char*)PSXM(a3)) +#define Rv0 ((char*)PSXM(v0)) +#define Rsp ((char*)PSXM(sp)) + +void bios_write() { // 0x35/0x03 + + + if (a0 == 1) { // stdout + char *ptr = Ra1; + + while (a2 > 0) { + SysPrintf(COLOR_RED "%c" COLOR_RESET, *ptr++); a2--; + } + pc0 = ra; return; + } +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("bios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2); +#endif + + v0 = -1; + + pc0 = ra; +} + +void bios_printf() { // 3f + char tmp[1024]; + char tmp2[1024]; + unsigned long save[4]; + char *ptmp = tmp; + int n=1, i=0, j; + + memcpy(save, (char*)PSXM(sp), 4*4); + psxMu32(sp) = a0; + psxMu32(sp + 4) = a1; + psxMu32(sp + 8) = a2; + psxMu32(sp + 12) = a3; + + while (Ra0[i]) { + switch (Ra0[i]) { + case '%': + j = 0; + tmp2[j++] = '%'; +_start: + switch (Ra0[++i]) { + case '.': + case 'l': + tmp2[j++] = Ra0[i]; goto _start; + default: + if (Ra0[i] >= '0' && Ra0[i] <= '9') { + tmp2[j++] = Ra0[i]; + goto _start; + } + break; + } + tmp2[j++] = Ra0[i]; + tmp2[j] = 0; + + switch (Ra0[i]) { + case 'f': case 'F': + ptmp+= sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break; + case 'a': case 'A': + case 'e': case 'E': + case 'g': case 'G': + ptmp+= sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break; + case 'p': + case 'i': + case 'd': case 'D': + case 'o': case 'O': + case 'x': case 'X': + ptmp+= sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break; + case 'c': + ptmp+= sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break; + case 's': + ptmp+= sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break; + case '%': + *ptmp++ = Ra0[i]; break; + } + i++; + break; + default: + *ptmp++ = Ra0[i++]; + } + } + *ptmp = 0; + + memcpy((char*)PSXM(sp), save, 4*4); + + SysPrintf(COLOR_RED "%s" COLOR_RESET, tmp); + + pc0 = ra; +} + +void bios_putchar () { // 3d + char tmp[12]; + + sprintf (tmp,"%c",(char)a0); + SysPrintf(tmp); + + pc0 = ra; +} + +void bios_puts () { // 3e/3f + SysPrintf(Ra0); + + pc0 = ra; +} + +void (*biosA0[256])(); +void (*biosB0[256])(); +void (*biosC0[256])(); + +void psxBiosInit() { + int i; + + for(i = 0; i < 256; i++) { + biosA0[i] = NULL; + biosB0[i] = NULL; + biosC0[i] = NULL; + } + biosA0[0x3e] = bios_puts; + biosA0[0x3f] = bios_printf; + + biosB0[0x3d] = bios_putchar; + biosB0[0x3f] = bios_puts; + +} + +void psxBiosShutdown() { +} + diff --git a/PsxBios.h b/PsxBios.h new file mode 100644 index 0000000000..1ac0fe7049 --- /dev/null +++ b/PsxBios.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXBIOS_H__ +#define __PSXBIOS_H__ + +extern char *biosA0n[256]; +extern char *biosB0n[256]; +extern char *biosC0n[256]; + +void psxBiosInit(); +void psxBiosShutdown(); +void psxBiosException(); +void psxBiosFreeze(int Mode); + +extern void (*biosA0[256])(); +extern void (*biosB0[256])(); +extern void (*biosC0[256])(); + +#endif /* __PSXBIOS_H__ */ diff --git a/PsxBios2.h b/PsxBios2.h new file mode 100644 index 0000000000..a0c664024a --- /dev/null +++ b/PsxBios2.h @@ -0,0 +1,94 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/***** sysmem imageInfo +00000800: 00 16 00 00 70 14 00 00 ¦ 01 01 00 00 01 00 00 00 +0000 next: .word ? //00001600 +0004 name: .word ? //00001470 +0008 version: .half ? //0101 +000A flags: .half ? //---- +000C index: .half ? //0001 +000E field_E: .half ? //---- +00000810: 90 08 00 00 A0 94 00 00 ¦ 30 08 00 00 40 0C 00 00 +0010 entry: .word ? //00000890 +0014 gp_value: .word ? //000094A0 +0018 p1_vaddr: .word ? //00000830 +001C text_size: .word ? //00000C40 +00000820: 40 00 00 00 10 00 00 00 ¦ 00 00 00 00 00 00 00 00 +0020 data_size: .word ? //00000040 +0024 bss_size: .word ? //00000010 +0028 field_28: .word ? //-------- +002C field_2C: .word ? //-------- +*****/ + +#ifndef __PSX_BIOS_H__ +#define __PSX_BIOS_H__ + +typedef struct { + u32 next, //+00 + name; //+04 + u16 version, //+08 + flags, //+0A + index, //+0C + _unkE; //+0E + u32 entry, //+10 + _gp, //+14 + vaddr, //+18 + text_size, //+1C + data_size, //+20 + bss_size, //+24 + _pad28, //+28 + _pad2C; //+2C +} irxImageInfo; //=30 + +typedef struct { + int active; + u32 server; + u32 fhandler; +} _sifServer; + +#define SIF_SERVERS 32 + +_sifServer sifServer[SIF_SERVERS]; + +// max modules/funcs + +#define IRX_MODULES 64 +#define IRX_FUNCS 256 + +typedef struct { + u32 num; + u32 entry; +} irxFunc; + +typedef struct { + int active; + u32 name[2]; + irxFunc funcs[IRX_FUNCS]; +} irxModule; + +irxModule irxMod[IRX_MODULES]; + + +void iopModulesInit(); +int iopSetImportFunc(u32 *ptr); +int iopSetExportFunc(u32 *ptr); +void sifServerCall(u32 server, u32 num, char *bin, int insize, char *bout, int outsize); +void sifAddServer(u32 server, u32 fhandler); + +#endif diff --git a/PsxCommon.h b/PsxCommon.h new file mode 100644 index 0000000000..36b0e73a22 --- /dev/null +++ b/PsxCommon.h @@ -0,0 +1,50 @@ +/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOMMON_H__ +#define __PSXCOMMON_H__ + +#include +#include "PS2Etypes.h" + +//#include "Common.h" +#include "System.h" +#include + +long LoadCdBios; +int cdOpenCase; + +#include "Plugins.h" +#include "R3000A.h" +#include "PsxMem.h" +#include "PsxHw.h" +#include "PsxBios.h" +#include "PsxDma.h" +#include "PsxCounters.h" +//#include "Mdec.h" +#include "CdRom.h" +#include "Sio.h" +//#include "Spu.h" +//#include "Decode_XA.h" +//#include "Misc.h" +#include "Debug.h" +//#include "Gte.h" +//#include "PsxGPU.h" +#include "PsxSio2.h" +#include "CDVD.h" + +#endif /* __PSXCOMMON_H__ */ diff --git a/PsxCounters.c b/PsxCounters.c new file mode 100644 index 0000000000..f8d2d822c7 --- /dev/null +++ b/PsxCounters.c @@ -0,0 +1,642 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "PsxCommon.h" + +psxCounter psxCounters[8]; +u32 psxNextCounter, psxNextsCounter; +static int cnts = 6; +u8 psxhblankgate = 0; + +static void psxRcntUpd16(u32 index) { + psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle; + + psxCounters[index].Cycle = (0xffff - (psxRcntRcount16(index)&0xffff)) * psxCounters[index].rate; + psxCounters[index].CycleT = (psxCounters[index].target - psxRcntRcount16(index)) * psxCounters[index].rate; +} + +static void psxRcntUpd32(u32 index) { + psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle; + + psxCounters[index].Cycle = (0xffffffff - ((u32)psxRcntRcount32(index)&0xffffffff)) * psxCounters[index].rate; + psxCounters[index].CycleT = (psxCounters[index].target - (u32)psxRcntRcount32(index)) * psxCounters[index].rate; +} + +static void psxRcntReset16(u32 index) { + psxCounters[index].count = 0; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd16(index); +} + +static void psxRcntReset32(u32 index) { + psxCounters[index].count = 0; + //psxCounters[index].otarget = 0x10000; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd32(index); +} + +static void psxRcntSet() { + u32 c; + int i; + + /*if (Config.SafeCnts) { + psxNextCounter = 0; + psxNextsCounter = 0; + return; + }*/ + + psxNextCounter = 0xffffffff; + psxNextsCounter = psxRegs.cycle; + + for (i=0; i<3; i++) { + c = (u32)(0xffff - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + if(psxCounters[i].mode & 0x08000000) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + for (i=3; i<7; i++) { + c = (u32)(0xffffffff - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + if(psxCounters[i].mode & 0x08000000) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + +// SysPrintf("psxRcntSet: %x (cycle)\n", psxNextCounter, psxRegs.cycle); +} + + +void psxRcntInit() { + int i; + + memset(psxCounters, 0, sizeof(psxCounters)); + + for (i=0; i<3; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0xffff; + } + for (i=3; i<6; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0xffffffff; + } + + psxCounters[0].interrupt = 0x10; + psxCounters[1].interrupt = 0x20; + psxCounters[2].interrupt = 0x40; + + psxCounters[3].interrupt = 0x04000; + psxCounters[4].interrupt = 0x08000; + psxCounters[5].interrupt = 0x10000; + + if (SPU2async != NULL) { + cnts = 7; + + psxCounters[6].rate = 1; + psxCounters[6].target = 768*64; + psxCounters[6].mode = 0x8; + } else cnts = 6; + + for (i=0; i<3; i++) + psxRcntUpd16(i); + for (i=3; i<6; i++) + psxRcntUpd32(i); + for (i=6; i> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u16)psxRcntRcount16(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + //Do nothing + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntUpd16(i); //Gate Starts counting from here + break; + case 0x3: //GATE_ON_Start + //Do Nothing, already started and counting + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u32)psxRcntRcount32(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + //Do nothing + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntUpd32(i); //Gate Starts counting from here + break; + case 0x3: //GATE_ON_Start + //Do Nothing, already started and counting + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} +void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts + int i = counter; + + if(counter < 3){ //Gates for 16bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + if(counter == 0) psxhblankgate |= 1; + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd16(i); + break; + case 0x1: //GATE_ON_ClearStart + psxRcntReset16(i); + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset16(i); + break; + case 0x3: //GATE_ON_Start + if(psxCounters[i].mode & 0x10000000)psxCounters[i].count += (u16)psxRcntRcount16(i); //Save the count if not first cycle + psxRcntUpd16(i); + psxCounters[i].mode |= 0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd32(i); + break; + case 0x1: //GATE_ON_ClearStart + psxRcntReset32(i); + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset32(i); + break; + case 0x3: //GATE_ON_Start + if(psxCounters[i].mode & 0x10000000)psxCounters[i].count += (u32)psxRcntRcount32(i); //Save the count if not first cycle + psxRcntUpd32(i); + psxCounters[i].mode |= 0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} + +void _testRcnt16target(int i) { + psxCounters[i].mode|= 0x0800; // Target flag +if (!(psxCounters[i].mode & 0x08000000) && psxCounters[i].mode & 0x10) { // Target interrupt + +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] target 0x%x >= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount16(i), psxCounters[i].target); +#endif + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + } + + if (psxCounters[i].mode & 0x08) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd16(i);//psxRcntReset16(i); + //psxCounters[i].mode|= 0x0C00; // Interrupt flag + } + if(!(psxCounters[i].mode & 0x40)) psxCounters[i].mode|= 0x08000000; + else { + psxRcntWtarget16(i, psxRcntRcount16(i) + psxCounters[i].target); //Repeat Interrupt + } +} + +void _testRcnt16overflow(int i) { + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount16(i), psxCounters[i].count); +#endif + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + + psxCounters[i].count = 0; + psxRcntUpd16(i);//psxRcntReset16(i); + //psxCounters[i].mode|= 0x1400; // Overflow flag +} + +void _testRcnt32target(int i) { + psxCounters[i].mode|= 0x0800; // Target flag + if (!(psxCounters[i].mode & 0x08000000) && psxCounters[i].mode & 0x10) { // Target interrupt +/*#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] target 0x%x >= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount32(i), psxCounters[i].target); +#endif*/ + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + } + + if (psxCounters[i].mode & 0x08) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd32(i); + //psxCounters[i].mode|= 0x0C00; // Interrupt flag + } + if(!(psxCounters[i].mode & 0x40))psxCounters[i].mode|= 0x08000000; + else { + psxRcntWtarget32(i, psxRcntRcount32(i) + psxCounters[i].target); //Repeat Interrupt + } +} + +void _testRcnt32overflow(int i) { + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount32(i), psxCounters[i].count); +#endif + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + psxCounters[i].count = 0; + psxRcntUpd32(i);//psxRcntReset32(i); + //psxCounters[i].mode|= 0x1400; // Overflow flag +} + +void _testRcnt16(int i) { + //if(!(psxCounters[i].mode & 0x08000000)) { + if (psxRcntCycles(i) >= psxCounters[i].target) + _testRcnt16target(i); + //} + + if (psxRcntCycles(i) >= 0xffff) { + _testRcnt16overflow(i); + psxCounters[i].count = 0; + psxRcntUpd16(i); + } + + /* mode & 0x08000000 means target interrupt already happened, + if so don't retest the target */ + //return; + + +} + +void _testRcnt32(int i) { + + //if (!(psxCounters[i].mode & 0x08000000)) { + + if (psxRcntCycles(i) >= psxCounters[i].target) + _testRcnt32target(i); + + //} + + if (psxRcntCycles(i) >= 0xffffffff) { + _testRcnt32overflow(i); + psxCounters[i].count = 0; + psxRcntUpd32(i); + } + + + /* mode & 0x08000000 means target interrupt already happened, + if so don't retest the target */ + +} + +void psxRcntUpdate() { + _testRcnt16(0); + _testRcnt16(1); + _testRcnt16(2); + _testRcnt32(3); + _testRcnt32(4); + _testRcnt32(5); + + if (cnts >= 7) { + if (psxRcntCycles(6) >= psxCounters[6].target) { + SPU2async((u32)(psxRegs.cycle - psxCounters[6].sCycleT)); + psxRcntReset16(6); + } + } + + psxRcntSet(); +} + +void psxRcntWcount16(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif +#ifdef PCSX2_DEVBUILD + //SysPrintf("Write to 16bit count reg counter %x\n", index); +#endif + //psxCounters[index].mode &= ~0x08001C00; + psxCounters[index].count = 0; + psxRcntUpd16(index); + psxRcntSet(); +} + +void psxRcntWcount32(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif +#ifdef PCSX2_DEVBUILD + //SysPrintf("Write to 32bit count reg counter %x\n", index); +#endif + //psxCounters[index].mode &= ~0x08001C00; + psxCounters[index].count = 0; + psxRcntUpd32(index); + psxRcntSet(); +} + +void psxRcnt0Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[0] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 0 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[0].mode & 0x3ff)) { + return; + }*/ + psxCounters[0].mode = value; + psxCounters[0].mode|= 0x0400; + //psxCounters[0].count = psxRcntRcount16(0); + psxCounters[0].rate = 1; + + + if(value & 0x100) psxCounters[0].rate = PSXPIXEL; + // Need to set a rate and target + /*if(psxCounters[0].mode & 0x1){ + // psxCounters[0].mode &= ~0x18101C00; + psxRcntReset16(0); + } else {*/ + psxCounters[0].count = 0; + psxRcntUpd16(0); + psxRcntSet(); + //} +} + +void psxRcnt1Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[1] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 1 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[1].mode & 0x3ff)) { + return; + }*/ + psxCounters[1].mode = value; + psxCounters[1].mode|= 0x0400; + //psxCounters[1].count = psxRcntRcount16(1); + psxCounters[1].rate = 1; + + if(value & 0x100)psxCounters[1].rate = PSXHBLANK; + + /*if(psxCounters[1].mode & 0x1){ + //psxCounters[1].mode &= ~0x18101C00; + psxRcntReset16(1); + } else {*/ + psxCounters[1].count = 0; + psxRcntUpd16(1); + psxRcntSet(); + //} +} + +void psxRcnt2Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[2] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 2 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[2].mode & 0x3ff)) { + return; + }*/ + + psxCounters[2].mode = value; + psxCounters[2].mode|= 0x0400; + //psxCounters[2].count = psxRcntRcount16(2); + switch(value & 0x200){ + case 0x200: + psxCounters[2].rate = 8; + break; + case 0x000: + psxCounters[2].rate = 1; + break; + } + +if(psxCounters[2].mode & 0x1){ + SysPrintf("Gate set on IOP C2, disabling\n"); + psxCounters[2].mode|= 0x1000000; +} + // Need to set a rate and target + psxCounters[2].count = 0; + psxRcntUpd16(2); + psxRcntSet(); +} + +void psxRcnt3Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[3] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 3 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[3].mode & 0x3ff)) { + return; + }*/ + psxCounters[3].mode = value; + //psxCounters[3].count = psxRcntRcount32(3); + psxCounters[3].rate = 1; + psxCounters[3].mode|= 0x0400; + if(value & 0x100)psxCounters[3].rate = PSXHBLANK; + + /*if(psxCounters[3].mode & 0x1){ + //psxCounters[3].mode &= ~0x18101C00; + psxRcntReset32(3); + } else {*/ + psxCounters[3].count = 0; + psxRcntUpd32(3); + psxRcntSet(); + //} +} + +void psxRcnt4Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[4] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 4 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[4].mode & 0x3ff)) { + return; + }*/ + psxCounters[4].mode = value; + psxCounters[4].mode|= 0x0400; + //psxCounters[4].count = psxRcntRcount32(4); + switch(value & 0x6000){ + case 0x0000: + psxCounters[4].rate = 1; + break; + case 0x2000: + psxCounters[4].rate = 8; + break; + case 0x4000: + psxCounters[4].rate = 16; + break; + case 0x6000: + psxCounters[4].rate = 256; + break; + } + // Need to set a rate and target +if(psxCounters[4].mode & 0x1){ + SysPrintf("Gate set on IOP C4, disabling\n"); + psxCounters[4].mode|= 0x1000000; +} + psxCounters[4].count = 0; + psxRcntUpd32(4); + psxRcntSet(); +} + +void psxRcnt5Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[5] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 5 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[5].mode & 0x3ff)) { + return; + }*/ +#ifdef PCSX2_DEVBUILD + //SysPrintf("IOP writeCmode[5] = %lx\n", value); +#endif + psxCounters[5].mode = value; + psxCounters[5].mode|= 0x0400; + //psxCounters[5].count = psxRcntRcount32(5); + switch(value & 0x6000){ + case 0x0000: + psxCounters[5].rate = 1; + break; + case 0x2000: + psxCounters[5].rate = 8; + break; + case 0x4000: + psxCounters[5].rate = 16; + break; + case 0x6000: + psxCounters[5].rate = 256; + break; + } + // Need to set a rate and target +if(psxCounters[5].mode & 0x1){ + SysPrintf("Gate set on IOP C5, disabling\n"); + psxCounters[5].mode|= 0x1000000; +} + psxCounters[5].count = 0; + psxRcntUpd32(5); + psxRcntSet(); +} + +void psxRcntWtarget16(int index, u32 value) { +/*#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget[%ld] = %lx\n", index, value); +#endif*/ + psxCounters[index].target = value; + //psxCounters[index].mode &= ~0x08000800; + //psxCounters[index].sCycleT = psxRegs.cycle; + psxCounters[index].CycleT = ((psxCounters[index].target - psxRcntRcount16(index)) * psxCounters[index].rate); +// psxRcntUpd16(index); + psxRcntSet(); +} + +void psxRcntWtarget32(int index, u32 value) { + psxCounters[index].target = value; + //psxCounters[index].mode &= ~0x08000800; + //psxCounters[index].sCycleT = psxRegs.cycle; + psxCounters[index].CycleT = ((psxCounters[index].target - (u32)psxRcntRcount32(index)) * psxCounters[index].rate); +/*#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget32[%ld] = %lx (count=%lx) ; sCycleT: %x CycleT: %x\n", + index, value, psxRcntRcount32(index), psxCounters[index].sCycleT, psxCounters[index].CycleT); +#endif*/ +// psxRcntUpd32(index); + psxRcntSet(); +} + +u16 psxRcntRcount16(int index) { + if(psxCounters[index].mode & 0x1000000) return 0; + return (u16)(psxCounters[index].count + ((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); +} + +u32 psxRcntRcount32(int index) { + if(psxCounters[index].mode & 0x1000000) return 0; + return (u32)(psxCounters[index].count + ((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); +} + +u64 psxRcntCycles(int index) { + if(psxCounters[index].mode & 0x1000000) return 0; + return (u64)(psxCounters[index].count + ((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); +} + +int psxRcntFreeze(gzFile f, int Mode) { + gzfreezel(psxCounters); + + return 0; +} diff --git a/PsxCounters.h b/PsxCounters.h new file mode 100644 index 0000000000..9bbe67bda9 --- /dev/null +++ b/PsxCounters.h @@ -0,0 +1,56 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOUNTERS_H__ +#define __PSXCOUNTERS_H__ + +typedef struct { + u32 count, mode, target; + u32 rate, interrupt, otarget; + u32 sCycle, Cycle; + u32 sCycleT, CycleT; +} psxCounter; + +psxCounter psxCounters[8]; + +u32 psxNextCounter, psxNextsCounter; + +void psxRcntInit(); +void psxRcntUpdate(); +void cntspu2async(); +void psxRcntWcount16(int index, u32 value); +void psxRcntWcount32(int index, u32 value); +void psxRcnt0Wmode(u32 value); +void psxRcnt1Wmode(u32 value); +void psxRcnt2Wmode(u32 value); +void psxRcnt3Wmode(u32 value); +void psxRcnt4Wmode(u32 value); +void psxRcnt5Wmode(u32 value); +void psxRcntWtarget16(int index, u32 value); +void psxRcntWtarget32(int index, u32 value); +u16 psxRcntRcount16(int index); +u32 psxRcntRcount32(int index); +u64 psxRcntCycles(int index); +int psxRcntFreeze(gzFile f, int Mode); + +void psxVSyncStart(); +void psxVSyncEnd(); +void psxCheckStartGate(int counter); +void psxCheckEndGate(int counter); + +#endif /* __PSXCOUNTERS_H__ */ diff --git a/PsxDma.c b/PsxDma.c new file mode 100644 index 0000000000..79319784d7 --- /dev/null +++ b/PsxDma.c @@ -0,0 +1,254 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "PsxCommon.h" +// Dma0/1 in Mdec.c +// Dma3 in CdRom.c +// Dma8 in PsxSpd.c +// Dma11/12 in PsxSio2.c +//static int spudmaenable[2]; +void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 4 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 4 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 4 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + switch (chcr) { + case 0x01000201: //cpu to spu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2writeDMA4Mem((u16 *)PSXM(madr), size); + HW_DMA4_MADR += size; + break; + case 0x01000200: //spu to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2readDMA4Mem((u16 *)PSXM(madr), size); + psxCpu->Clear(HW_DMA4_MADR, size); + HW_DMA4_MADR += size; + break; + + default: + SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } + //spudmaenable[0] = size; +} + +int psxDma4Interrupt() { + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + psxHu32(0x1070)|= 1<<9; + return 1; +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU + HW_DMA2_CHCR &= ~0x01000000; + psxDmaInterrupt(2); +} + +void psxDma6(u32 madr, u32 bcr, u32 chcr) { + u32 *mem = (u32 *)PSXM(madr); + +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr == 0x11000002) { + while (bcr--) { + *mem-- = (madr - 4) & 0xffffff; + madr -= 4; + } + mem++; *mem = 0xffffff; + } else { + // Unknown option +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + } + HW_DMA6_CHCR &= ~0x01000000; + psxDmaInterrupt(6); +} + +void psxDma7(u32 madr, u32 bcr, u32 chcr) { + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 7 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 7 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 7 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + switch (chcr) { + case 0x01000201: //cpu to spu2 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA7 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2writeDMA7Mem((u16 *)PSXM(madr), size); + HW_DMA7_MADR += size; + break; + case 0x01000200: //spu2 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2readDMA7Mem((u16 *)PSXM(madr), size); + psxCpu->Clear(HW_DMA7_MADR, size); + HW_DMA7_MADR += size; + break; + default: + SysPrintf("*** DMA 7 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } +} + +int psxDma7Interrupt() { + + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + return 1; + +} + +void psxDma9(u32 madr, u32 bcr, u32 chcr) { + + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc000]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR); +#endif + + psHu32(0x1000F240) |= 0x2000; + if (dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void psxDma10(u32 madr, u32 bcr, u32 chcr) { + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc400]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx\n", chcr, madr, bcr); +#endif + + psHu32(0x1000F240) |= 0x4000; + if (dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void psxDma8(u32 madr, u32 bcr, u32 chcr) { + int size; + + switch (chcr & 0x01000201) { + case 0x01000201: //cpu to dev9 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9writeDMA8Mem((u32*)PSXM(madr), size*8); + break; + case 0x01000200: //dev9 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9readDMA8Mem((u32*)PSXM(madr), size*8); + break; +#ifdef PSXDMA_LOG + default: + PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; +#endif + } + HW_DMA8_CHCR &= ~0x01000000; + psxDmaInterrupt2(1); +} + +int dev9Interrupt() { + if (dev9Handler == NULL) goto irq; + if (dev9Handler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<13; + return 1; +} + +void dev9Irq(int cycles) { + PSX_INT(20, (PSXCLK/cycles)); +} + +int usbInterrupt() { + if (usbHandler == NULL) goto irq; + if (usbHandler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<22; + return 1; +} + +void usbIrq(int cycles) { + PSX_INT(21, (PSXCLK/cycles)); +} + +void fwIrq() { + psxHu32(0x1070)|= 1<<24; +} + +void spu2DMA4Irq() { + //SysPrintf("IRQ DMA 4\n"); + SPU2interruptDMA4(); + //if(SPU2read(0x1f90019a) & 0xff) PSX_INT(4, (spudmaenable[0] * PSXSOUNDCLK) / BIAS); + HW_DMA4_BCR = 0; + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + //psxHu32(0x1070)|= 1<<9; + +} + +void spu2DMA7Irq() { + //SysPrintf("IRQ DMA 7\n"); + SPU2interruptDMA7(); + //if(SPU2read(0x1f90059a) & 0xff) PSX_INT(7, (spudmaenable[1] * PSXSOUNDCLK) / BIAS); + + HW_DMA7_BCR = 0; + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + //psxHu32(0x1070)|= 1<<9; +} + +void spu2Irq() { + psxHu32(0x1070)|= 1<<9; +} diff --git a/PsxDma.h b/PsxDma.h new file mode 100644 index 0000000000..9db6f175d6 --- /dev/null +++ b/PsxDma.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXDMA_H__ +#define __PSXDMA_H__ + +void psxDma2(u32 madr, u32 bcr, u32 chcr); +void psxDma3(u32 madr, u32 bcr, u32 chcr); +void psxDma4(u32 madr, u32 bcr, u32 chcr); +void psxDma6(u32 madr, u32 bcr, u32 chcr); +void psxDma7(u32 madr, u32 bcr, u32 chcr); +void psxDma8(u32 madr, u32 bcr, u32 chcr); +void psxDma9(u32 madr, u32 bcr, u32 chcr); +void psxDma10(u32 madr, u32 bcr, u32 chcr); + +int psxDma4Interrupt(); +int psxDma7Interrupt(); +int dev9Interrupt(); +DEV9handler dev9Handler; +void dev9Irq(int cycles); +int usbInterrupt(); +USBhandler usbHandler; +void usbIrq(int cycles); +void fwIrq(); +void spu2Irq(); + +#endif /* __PSXDMA_H__ */ diff --git a/PsxGPU.c b/PsxGPU.c new file mode 100644 index 0000000000..7bbf1d0299 --- /dev/null +++ b/PsxGPU.c @@ -0,0 +1,1067 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + + +u32 gpuStatus = 0x14802000; +int gpuMode = 0; +u8 gpuCmd; +int gpuDataC = 0; +int gpuDataP; +u32 gpuDataRet; +u32 gpuData[256]; +u32 gpuInfo[8] = {0, 0, 0, 0, 0, 0, 0, 2}; +int imageTransfer; +s16 imTX, imTXc, imTY, imTYc; +s16 imageX0, imageX1; +s16 imageY0, imageY1; + +// Draw Primitives + +void primPolyF3(unsigned char * baseAddr) { +/* PolyF3 prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyF3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + triangle(drawvram, prim.x0, prim.y0, prim.x1, prim.y1, prim.x2, prim.y2, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("PolyF3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyFT3(unsigned char * baseAddr) { +/* PolyFT3 prim; + V3D_f v[3]; + Cache *tex; + unsigned int c,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyFT3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + +// c = MAKERGB24(prim.r, prim.g, prim.b); + c = ((prim.r*2 + prim.g*2 + prim.b*2) / 3); if (c > 0xff) c = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, prim.u2)), + MIN(prim.v0, MIN(prim.v1, prim.v2)), + MAX(prim.u0, MIN(prim.u1, prim.u2)), + MAX(prim.v0, MIN(prim.v1, prim.v2))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[2]); + } + else triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[2]); + + pslog ("PolyFT3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyF4(unsigned char *baseAddr) { +/* PolyF4 prim; + unsigned int c; + int point[8]; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyF4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + point[0] = prim.x0; point[1] = prim.y0; + point[2] = prim.x1; point[3] = prim.y1; + point[4] = prim.x3; point[5] = prim.y3; + point[6] = prim.x2; point[7] = prim.y2; + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + polygon(drawvram, 4, point, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("PolyF4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primPolyFT4(unsigned char * baseAddr) { +/* PolyFT4 prim; + V3D_f v[4]; + Cache *tex; + unsigned int c, id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyFT4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + +// c = MAKERGB24(prim.r,prim.g,prim.b); + c = (prim.r*2 + prim.g*2 + prim.b*2) / 3; if (c > 0xff) c = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, MIN(prim.u2, prim.u3))), + MIN(prim.v0, MIN(prim.v1, MIN(prim.v2, prim.v3))), + MAX(prim.u0, MAX(prim.u1, MAX(prim.u2, prim.u3))), + MAX(prim.v0, MAX(prim.v1, MAX(prim.v2, prim.v3)))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; + v[3].u = prim.u3; v[3].v = prim.v3; v[3].c = c; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyFT4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d) c=%x", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0,c);*/ +} + +void primPolyG3(unsigned char *baseAddr) { +/* PolyG3 prim; + V3D_f v[3]; + unsigned int c0,c1,c2; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyG3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + + c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); + c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); + c2 = MAKERGB24(prim.r2, prim.g2, prim.b2); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; v[2].c = c2; + + triangle3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[2]); + + pslog("polyG3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyGT3(unsigned char *baseAddr) { +/* PolyGT3 prim; + V3D_f v[3]; + Cache *tex; + unsigned int c0,c1,c2,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyGT3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + +// c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); +// c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); +// c2 = MAKERGB24(prim.r2, prim.g2, prim.b2); + c0 = (prim.r0*2 + prim.g0*2 + prim.b0*2) / 3; if (c0 > 0xff) c0 = 0xff; + c1 = (prim.r1*2 + prim.g1*2 + prim.b1*2) / 3; if (c1 > 0xff) c1 = 0xff; + c2 = (prim.r2*2 + prim.g2*2 + prim.b2*2) / 3; if (c2 > 0xff) c2 = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, prim.u2)), + MIN(prim.v0, MIN(prim.v1, prim.v2)), + MAX(prim.u0, MAX(prim.u1, prim.u2)), + MAX(prim.v0, MAX(prim.v1, prim.v2))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c2; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[2]); + } + else triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[2]); + + pslog("polyGT3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyG4(unsigned char * baseAddr) { +/* PolyG4 prim; + V3D_f v[4]; + unsigned int c0,c1,c2,c3; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyG4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + + c0 = MAKERGB24(prim.r0,prim.g0,prim.b0); + c1 = MAKERGB24(prim.r1,prim.g1,prim.b1); + c2 = MAKERGB24(prim.r2,prim.g2,prim.b2); + c3 = MAKERGB24(prim.r3,prim.g3,prim.b3); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; v[2].c = c2; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; v[3].c = c3; + + if (prim.code & 2) return; + quad3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyG4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primPolyGT4(unsigned char *baseAddr) { +/* PolyGT4 prim; + V3D_f v[4]; + Cache *tex; + unsigned int c0,c1,c2,c3,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyGT4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + +// c0 = MAKERGB24(prim.r0,prim.g0,prim.b0); +// c1 = MAKERGB24(prim.r1,prim.g1,prim.b1); +// c2 = MAKERGB24(prim.r2,prim.g2,prim.b2); +// c3 = MAKERGB24(prim.r3,prim.g3,prim.b3); + c0 = (prim.r0*2 + prim.g0*2 + prim.b0*2) / 3; if (c0 > 0xff) c0 = 0xff; + c1 = (prim.r1*2 + prim.g1*2 + prim.b1*2) / 3; if (c1 > 0xff) c1 = 0xff; + c2 = (prim.r2*2 + prim.g2*2 + prim.b2*2) / 3; if (c2 > 0xff) c2 = 0xff; + c3 = (prim.r3*2 + prim.g3*2 + prim.b3*2) / 3; if (c3 > 0xff) c3 = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, MIN(prim.u2, prim.u3))), + MIN(prim.v0, MIN(prim.v1, MIN(prim.v2, prim.v3))), + MAX(prim.u0, MAX(prim.u1, MAX(prim.u2, prim.u3))), + MAX(prim.v0, MAX(prim.v1, MAX(prim.v2, prim.v3)))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c2; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; + v[3].u = prim.u3; v[3].v = prim.v3; v[3].c = c3; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyGT4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primLineF2(unsigned char *baseAddr) { +/* LineF2 prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(LineF2)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + line(drawvram, prim.x0, prim.y0, prim.x1, prim.y1, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineF2 : %d,%d - %d,%d : color = %x\n", + prim.x0,prim.y0,prim.x1,prim.y1,c);*/ +} + +void primLineF(unsigned char *baseAddr) { +/* unsigned int c,x,y,lx=0,ly=0; + unsigned int *baseAddri = (unsigned int *)baseAddr; + int i,j; + + if (norender) return; + + for (i=0;i<99;i++) + if (baseAddri[i]==0x55555555) + break; + + i--; + + c = MAKERGB15(baseAddr[0], baseAddr[1], baseAddr[2]); + + if (baseAddr[3] & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + for (j=0;j>16)&0xffff; + + x += offsX; + y += offsY; + + if (j>0) + line(drawvram, x, y, lx, ly, c); + + lx = x; + ly = y; + } + + if (baseAddr[3] & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineF vert = %d : color = %x\n", + i,c);*/ +} + +void primLineG2(unsigned char *baseAddr) { +/* LineG2 prim; + V3D_f v[2]; + unsigned int c0,c1; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(LineG2)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + + c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); + c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + triangle3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[1]); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineG2 : %d,%d - %d,%d : color = %x,%x\n", + prim.x0,prim.y0,prim.x1,prim.y1,c0,c1);*/ +} + +void primLineG(unsigned char *baseAddr) { +/* unsigned int c,x,y,lx=0,ly=0,lc=0; + unsigned int *baseAddri = (unsigned int *)baseAddr; + int i,j; + + if (norender) return; + + for (i=0;i<99;i++) + if (baseAddri[i]==0x55555555) + break; + + i--; + i/=2; + + + for (j=0;j>16)&0xffff; + + x += offsX; + y += offsY; + + if (j>0) + line(drawvram, x, y, lx, ly, c); + + lx = x; + ly = y; + lc = c; + } + + pslog ("LineG vert = %d\n", + i);*/ +} + +void primTileS(unsigned char * baseAddr) { +/* RectWH prim; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, ((short*)baseAddr)[4], ((short*)baseAddr)[5]);*/ +} + +void primSprtS(unsigned char * baseAddr) { +/* SprtWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite(&prim, ((short*)baseAddr)[6], ((short*)baseAddr)[7]);*/ +} + +void primTile1(unsigned char * baseAddr) { +/* RectWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 1, 1);*/ +} + +void primTile8(unsigned char * baseAddr) { +/* RectWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 8, 8);*/ +} + +void primSprt8(unsigned char * baseAddr) { +/* SprtWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite((SprtWH *)baseAddr, 8, 8);*/ +} + +void primTile16(unsigned char * baseAddr) { +/* RectWH prim; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 16, 16);*/ +} + +void primSprt16(unsigned char * baseAddr) { +/* SprtWH prim; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite(&prim, 16, 16);*/ +} + +// Command Primitives + +void primVoid(unsigned char * baseAddr) { +} + +void primClrCache(unsigned char * baseAddr) { +} + +void primBlkFill(unsigned char * baseAddr) { +/* Rect prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(Rect)); + + if ((prim.x > 1023) | (prim.y > 511)) return; + if (((prim.w + prim.x) > 1024) | ((prim.y + prim.h) > 512)) return; + if (prim.x < 0) prim.x = 0; + if (prim.y < 0) prim.y = 0; + if (prim.w > 1023) prim.w = 1023; + if (prim.h > 511) prim.h = 511; + + c = MAKERGB15(baseAddr[0],baseAddr[1],baseAddr[2]); + + pslog ("BlkFill %d,%d;%d,%d ,c=%x", + prim.x,prim.y,prim.w,prim.h,c); + + set_clip(drawvram, 0, 0, 1023, 511); + rectfill(drawvram, prim.x, prim.y, prim.w + prim.x - 1, prim.h + prim.y - 1, c); + SetClip();*/ +} + +void primMoveImage(unsigned char * baseAddr) { +/* short *gpuData = ((unsigned short *) baseAddr); + short imageSX,imageSY,imageDX,imageDY,imageW,imageH; + + imageSX = gpuData[2] & 0x3ff; + imageSY = gpuData[3] & 0x1ff; + + imageDX = gpuData[4] & 0x3ff; + imageDY = gpuData[5] & 0x1ff; + + imageW = gpuData[6] & 0xffff; + imageH = gpuData[7] & 0xffff; + + if((imageSY+imageH)>512) imageH=512-imageSY; + if((imageDY+imageH)>512) imageH=512-imageDY; + if((imageSX+imageW)>1024) imageW=1024-imageSX; + if((imageDX+imageW)>1024) imageW=1024-imageDX; + + pslog("MoveImage %d,%d %d,%d %d,%d\n", + imageSX, imageSY, imageDX, imageDY, imageW, imageH); + + UnsetClip(); + blit(vram, vram, imageSX, imageSY, imageDX, imageDY, imageW, imageH); + SetClip();*/ +} + +void primLoadImage(unsigned char * baseAddr) { + u32 gifTag[16]; + unsigned short *gpuData = ((unsigned short *) baseAddr); + + imageX0 = gpuData[2] & 0x3ff; + imageY0 = gpuData[3] & 0x1ff; + imageX1 = gpuData[4]; + imageY1 = gpuData[5]; + + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imageTransfer = 2; + +#ifdef GPU_LOG + GPU_LOG ("LoadImage %d,%d %d,%d\n", imageX0, imageY0, imageX0 + imageX1, imageY0 + imageY1); +#endif + + gifTag[0] = 3; // nloop = 3 + gifTag[1] = (1 << 28); // regs = 1 + gifTag[2] = 0xe; // ad reg + + gifTag[4] = 0; + gifTag[5] = ((1024/64) << 16) | 0; + gifTag[6] = 0x50; // bitbltbuf + + gifTag[8] = 0; + gifTag[9] = (imageY0 << 16) | imageX0; + gifTag[10] = 0x51; // trxpos + + gifTag[12] = imageX1; + gifTag[13] = imageY1; + gifTag[14] = 0x52; // trxreg + + GSgifTransfer3(gifTag, 4); +} + +void primStoreImage(unsigned char * baseAddr) { +/* unsigned long *gpuData = ((unsigned long *) baseAddr); + + imageX0 = (short)(gpuData[1] & 0x3ff); + imageY0 = (short)(gpuData[1]>>16) & 0x1ff; + imageX1 = (short)(gpuData[2] & 0xffff); + imageY1 = (short)((gpuData[2]>>16) & 0xffff); + + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imSize=imageY1*imageX1/2; + + imageTransfer = 3; + GpuStatus|=0x08000000; + + pslog ("StoreImage %d,%d %d,%d\n" + ,imageX0, imageY0, imageX0 + imageX1, imageY0 + imageY1);*/ +} + +// Enviroment Primitives + +void primTPage(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + TPage = (short)(gdata & 0x7ff); + textAddrX = (gdata&0xf)<<6; + textAddrY = (((gdata)<<4)&0x100)+(((gdata)>>2)&0x200); + textTP = (gdata & 0x180) >> 7; + textABR = (gdata >> 5) & 0x3; + textREST = (gdata&0x00ffffff)>>9; + + GpuStatus = (GpuStatus & ~0x7ff) | (TPage);*/ +} + +void primTWindow(unsigned char *baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + tWinW = gdata&0xf; + tWinH = (gdata>>4)&0xf; + tWinX = (gdata>>8)&0xf; + tWinY = (gdata>>12)&0xf; + + pslog("primTWindow %d,%d %d,%d\n", tWinX, tWinY, tWinW, tWinH);*/ +} + +void primAreaStart(unsigned char * baseAddr) { +/* unsigned int gdata = ((unsigned int *)baseAddr)[0]; + + clipX = gdata & 0x3ff; + clipY = (gdata>>10) & 0x1ff; + SetClip(); + pslog("primAreaStart %dx%d\n", clipX, clipY); + GpuInfo[3] = gdata & 0xffffff;*/ +} + +void primAreaEnd(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + clipW = (short)(gdata & 0x3ff); + clipH = (short)((gdata>>10) & 0x1ff); + SetClip(); + pslog("primAreaEnd %dx%d\n", clipW, clipH); + GpuInfo[4] = gdata & 0xffffff;*/ +} + +void primDrawOffset(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + offsX = (short)(gdata & 0x3ff); + offsY = (short)((gdata >> 11) & 0x1ff); + pslog("primDrawOffset %dx%d\n", offsX, offsY); + GpuInfo[5] = gdata & 0xffffff;*/ +} + +void primMask(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + md = gdata & 1; + me = gdata & 2; + GpuStatus = (GpuStatus & ~(3<<11)) | ((gdata&3)<<11);*/ +} + +// Drawing Helper Functions +/* +void drawSprite(SprtWH *prim, short w, short h) { + Cache *sprt; + unsigned int id; + + prim->x+=offsX; + prim->y+=offsY; + + id = (prim->clut << 16) | TPage; +// sprt = CacheGet(id, prim->u, prim->v, w + prim->u, h + prim->v); + sprt = CacheGet(id, 0, 0, 256, 256); + + if ((prim->r >= 0x80) & (prim->g >= 0x80) & (prim->b >= 0x80) & (!(prim->code & 2))) { + masked_blit(sprt->tex, drawvram, prim->u, prim->v, prim->x, prim->y, w, h); + + pslog ("Sprite : %d,%d - %dx%d (c=%x)- u,v: %d,%d (semi-transparency=%d) tex id=%x", + prim->x,prim->y,w,h,0x808080,prim->u,prim->v,(prim->code&2)!=0,id); + } + else { + V3D_f v[4]; + unsigned int c; + +// c = MAKERGB24(prim->r*2,prim->g*2,prim->b*2); + c = (prim->r*2 + prim->g*2 + prim->b*2) / 3; if (c > 0xff) c = 0xff; + + v[0].x = prim->x; v[0].y = prim->y; v[0].z = 0; + v[0].u = prim->u; v[0].v = prim->v; v[0].c = c; + v[1].x = prim->x; v[1].y = prim->y + h; v[1].z = 0; + v[1].u = prim->u; v[1].v = prim->v + h; v[1].c = c; + v[2].x = prim->x + w; v[2].y = prim->y; v[2].z = 0; + v[2].u = prim->u + w; v[2].v = prim->v; v[2].c = c; + v[3].x = prim->x + w; v[3].y = prim->y + h; v[3].z = 0; + v[3].u = prim->u + w; v[3].v = prim->v + h; v[3].c = c; + + if (prim->code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, sprt->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, sprt->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("Sprite : %d,%d - %dx%d (c=%x)- u,v: %d,%d (semi-transparency=%d) tex id=%x", + prim->x,prim->y,w,h,c,prim->u,prim->v,(prim->code&2)!=0,id); + } + +} + +void drawRect(RectWH *prim, short w, short h) { + unsigned int c; + + prim->x+=offsX; + prim->y+=offsY; + + c = MAKERGB15(prim->r,prim->g,prim->b); + + if (prim->code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + rectfill(drawvram, prim->x, prim->y, w + prim->x - 1, h + prim->y - 1, c); + if (prim->code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("Rectangle %d,%d %dx%d (semi-transparency=%d) c=%x", + prim->x,prim->y,w,h,(prim->code & 2)!=0,c); +}*/ + +// + +void primNI(unsigned char *bA) { +// if (bA[3]) pslog("PRIM: *NI* %02x",bA[3]); +} + + +unsigned char primTableC[256] = { + 1,1,3,0,0,0,0,0, // 00 + 0,0,0,0,0,0,0,0, // 08 + 0,0,0,0,0,0,0,0, // 10 + 0,0,0,0,0,0,0,0, // 18 + 4,4,4,4,7,7,7,7, // 20 + 5,5,5,5,9,9,9,9, // 28 + 6,6,6,6,9,9,9,9, // 30 + 8,8,8,8,12,12,12,12, // 38 + 3,3,3,3,0,0,0,0, // 40 + 5,5,5,5,6,6,6,6, // 48 + 4,4,4,4,0,0,0,0, // 50 + 7,7,7,7,9,9,9,9, // 58 + 3,3,3,3,4,4,4,4, // 60 + 2,2,2,2,0,0,0,0, // 68 + 2,2,2,2,3,3,3,3, // 70 + 2,2,2,2,3,3,3,3, // 78 + 4,0,0,0,0,0,0,0, // 80 + 0,0,0,0,0,0,0,0, // 88 + 0,0,0,0,0,0,0,0, // 90 + 0,0,0,0,0,0,0,0, // 98 + 3,0,0,0,0,0,0,0, // a0 + 0,0,0,0,0,0,0,0, // a8 + 0,0,0,0,0,0,0,0, // b0 + 0,0,0,0,0,0,0,0, // b8 + 3,0,0,0,0,0,0,0, // c0 + 0,0,0,0,0,0,0,0, // c8 + 0,0,0,0,0,0,0,0, // d0 + 0,0,0,0,0,0,0,0, // d8 + 0,1,1,1,1,1,1,0, // e0 + 0,0,0,0,0,0,0,0, // e8 + 0,0,0,0,0,0,0,0, // f0 + 0,0,0,0,0,0,0,0 // f8 +}; + +void (*primTableJ[256])(unsigned char *) = { + // 00 + primVoid,primClrCache,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primLineF,primLineF,primLineF,primLineF,primNI,primNI,primNI,primNI, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primLineG,primLineG,primLineG,primLineG,primNI,primNI,primNI,primNI, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, + // 70 + primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,primTPage,primTWindow,primAreaStart,primAreaEnd,primDrawOffset,primMask,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + +u32 cd[4]; +int cdC = 0; + +__inline void writePixel(short x, short y, u16 p) { + u32 gifTag[16]; + + cd[cdC] = ((p & 0x7c00) << 9) | + ((p & 0x03e0) << 6) | + ((p & 0x001f) << 3); + cdC++; + if (cdC < 4) return; + cdC = 0; + + gifTag[0] = 1; + gifTag[1] = 2 << 26; + + GSgifTransfer3(gifTag, 1); + GSgifTransfer3(cd, 1); +} + +void GPU_writeData(u32 data) { + gpuDataRet = data; + + if (imageTransfer == 2) { + // image transfer to VRAM + if (imTYc>0 && imTXc>0) { + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) { + writePixel(imTX, imTY, (u16)data); + } + + imTX++; imTXc--; + if (imTXc<=0) { + imTX = imageX0; imTXc = imageX1; + imTYc--; imTY++; + } + if (imTYc <= 0) { imageTransfer = 0; return; } + + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) { + writePixel(imTX, imTY, (u16)(data>>16)); + } + + imTX++; imTXc--; + if (imTXc<=0) { + imTX = imageX0; imTXc = imageX1; + imTYc--; imTY++; + } + if (imTYc <= 0) { imageTransfer = 0; return; } + + return; + } + else imageTransfer = 0; + } + +#ifdef GPU_LOG + GPU_LOG("!GPU! DATA = %08x\n", data); +#endif + + if (gpuDataC == 0) { + gpuCmd = (u8)(data >> 24); + gpuDataC = primTableC[gpuCmd]; + if (gpuDataC) { + gpuData[0] = data; + gpuDataP = 1; + } else { +#ifdef GPU_LOG + GPU_LOG("GPU ERROR CMD: %x, data=%x\n", gpuCmd, data); +#endif + return; + } + } else { + if (gpuDataP >= 256) return; + gpuData[gpuDataP++] = data; + } + + if (gpuDataP == gpuDataC) { + gpuDataP = gpuDataC = 0; +#ifdef GPU_LOG + GPU_LOG("Gpu(writeData) Command %x\n", gpuCmd); +#endif + primTableJ[gpuCmd]((u8*)gpuData); + } +} + +void GPU_writeStatus(u32 data) { +// u32 gifTag[16]; + + switch (data >> 24) { + case 0x00: +/* gifTag[0] = 2; // nloop = 2 + gifTag[1] = (1 << 28); // regs = 1 + gifTag[2] = 0xe; // ad reg + + gifTag[4] = 0; + gifTag[5] = ((1024/64) << 16) | 0; + gifTag[6] = 0x50; // bitbltbuf + + gifTag[8] = 320; + gifTag[9] = 240; + gifTag[10] = 0x52; // trxreg + + GSgifTransfer3(gifTag, 3);*/ + GSwrite64(0x12000070, (1024/64) << 9); + break; + + case 0x10: + switch (data&7) { + case 3: + case 4: + case 5: + case 7: + gpuDataRet = gpuInfo[data&7]; + break; + default: +#ifdef GPU_LOG + GPU_LOG("GPU INFO UNK: %x\n", data); +#endif + break; + } + break; + } +} + +u32 GPU_readData() { + return gpuDataRet; +} + +u32 GPU_readStatus() { + gpuStatus^= 0x80000000; + return gpuStatus; +} + +void GPU_writeDataMem(u32 *pMem, int iSize) { +/* u32 gifTag[16]; + int i; + u16 *ptr = (u16*)pMem;*/ + +#ifdef GPU_LOG + GPU_LOG("GPUwriteDataMem: %d\n", iSize); +#endif + + while (iSize) { + GPU_writeData(*pMem); + pMem++; iSize--; + } + +/*#ifdef GPU_LOG + GPU_LOG("GPUwriteDataMem: %d\n", iSize); +#endif + + if (iSize > 0x7fff) { + } else { + gifTag[0] = iSize & 0x7fff; + gifTag[1] = 2 << 26; + + GSgifTransfer3(gifTag, 1); +// GSgifTransfer3(pMem, iSize); + GSgifTransfer3(ptr1, iSize); + } + imageTransfer = 0;*/ +} + +void GPU_readDataMem(u32 *pMem, int iSize) { +} + +void GPU_dmaChain(u32 *baseAddrL, u32 addr) { + unsigned long dmaMem; + unsigned char * baseAddrB; + unsigned char count; + unsigned char cmd; + + baseAddrB = (unsigned char*) baseAddrL; + + for (;;) { + count = baseAddrB[addr+3]; + dmaMem = addr+4; + while (count) { + if (imageTransfer == 2) { + GPU_writeData(baseAddrL[dmaMem/4]); + dmaMem+=4; + count--; + continue; + } + cmd = baseAddrB[dmaMem+3]; + if (primTableC[cmd] == 0) { + dmaMem+=4; + count--; + } else { +#ifdef GPU_LOG + GPU_LOG("Gpu(DmaChain) Command %x : %x\n", cmd, baseAddrL[dmaMem/4]); +#endif + primTableJ[cmd]((u8*)baseAddrL + dmaMem); + dmaMem+=(primTableC[cmd]*4); + count-=primTableC[cmd]; + } + } + addr = baseAddrL[addr/4]&0xffffff; + if (addr <= 0 || addr == 0xffffff) break; + addr&=0x7fffff; + } +} diff --git a/PsxGPU.h b/PsxGPU.h new file mode 100644 index 0000000000..0126298d21 --- /dev/null +++ b/PsxGPU.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXGPU_H__ +#define __PSXGPU_H__ + +#include "PS2Etypes.h" + +void GPU_writeData(u32 data); +void GPU_writeStatus(u32 data); +u32 GPU_readData(); +u32 GPU_readStatus(); +void GPU_writeDataMem(u32 *pMem, int iSize); +void GPU_readDataMem(u32 *pMem, int iSize); +void GPU_dmaChain(u32 *baseAddrL, u32 addr); + +#endif /* __PSXGPU_H__ */ diff --git a/PsxHw.c b/PsxHw.c new file mode 100644 index 0000000000..46f1299fda --- /dev/null +++ b/PsxHw.c @@ -0,0 +1,2850 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +#include "ir5900.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +// NOTE: Any modifications to read/write fns should also go into their const counterparts + +void psxHwReset() { +/* if (Config.Sio) psxHu32(0x1070) |= 0x80; + if (Config.SpuIrq) psxHu32(0x1070) |= 0x200;*/ + + memset(psxH, 0, 0x10000); + +// mdecInit(); //intialize mdec decoder + cdrReset(); + cdvdReset(); + psxRcntInit(); + sioInit(); +// sio2Reset(); +} + +u8 psxHwRead8(u32 add) { + u8 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread8(add); + } + + switch (add) { + case 0x1f801040: hard = sioRead8();break; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + + case 0x1f80146e: // DEV9_R_REV + return DEV9read8(add); + + case 0x1f801800: hard = cdrRead0(); break; + case 0x1f801801: hard = cdrRead1(); break; + case 0x1f801802: hard = cdrRead2(); break; + case 0x1f801803: hard = cdrRead3(); break; + + case 0x1f803100: // PS/EE/IOP conf related + hard = 0x10; // Dram 2M + break; + + case 0x1F808264: + hard = sio2_fifoOut();//sio2 serial data feed/fifo_out +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read8 DATAOUT %08X\n", hard); +#endif + return hard; + + default: + hard = psxHu8(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +#define CONSTREAD8_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R8toR(EAX, EAX); \ + else MOVZX32R8toR(EAX, EAX); \ +} \ + +static u32 s_16 = 0x10; + +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign) { + + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD8_CALL(USBread8); + // since calling from different dll, esp already changed + return 1; + } + + switch (add) { + case 0x1f801040: + CONSTREAD8_CALL(sioRead8); + return 1; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD8_CALL(DEV9read8); + return 1; + + case 0x1f801800: CONSTREAD8_CALL(cdrRead0); return 1; + case 0x1f801801: CONSTREAD8_CALL(cdrRead1); return 1; + case 0x1f801802: CONSTREAD8_CALL(cdrRead2); return 1; + case 0x1f801803: CONSTREAD8_CALL(cdrRead3); return 1; + + case 0x1f803100: // PS/EE/IOP conf related + if( IS_XMMREG(x86reg) ) SSEX_MOVD_M32_to_XMM(x86reg&0xf, (u32)&s_16); + else if( IS_MMXREG(x86reg) ) MOVDMtoMMX(x86reg&0xf, (u32)&s_16); + else MOV32ItoR(x86reg, 0x10); + return 0; + + case 0x1F808264: //sio2 serial data feed/fifo_out + CONSTREAD8_CALL(sio2_fifoOut); + return 1; + + default: + _eeReadConstMem8(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; + } +} + +u16 psxHwRead16(u32 add) { + u16 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread16(add); + } + + switch (add) { +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070)); + return psxHu16(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074)); + return psxHu16(0x1074); +#endif + + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801044: + hard = sio.StatReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801048: + hard = sio.ModeReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104a: + hard = sio.CtrlReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104e: + hard = sio.BaudReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + + //Serial port stuff not support now ;P + // case 0x1f801050: hard = serial_read16(); break; + // case 0x1f801054: hard = serial_status_read(); break; + // case 0x1f80105a: hard = serial_control_read(); break; + // case 0x1f80105e: hard = serial_baud_read(); break; + + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801104: + hard = psxCounters[0].mode; + psxCounters[0].mode&= ~0x1800; + psxCounters[0].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801114: + hard = psxCounters[1].mode; + psxCounters[1].mode&= ~0x1800; + psxCounters[1].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801124: + hard = psxCounters[2].mode; + psxCounters[2].mode&= ~0x1800; + psxCounters[2].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read16: %x\n", hard); +#endif + return hard; + + case 0x1f80146e: // DEV9_R_REV + return DEV9read16(add); + + case 0x1f801480: + hard = (u16)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = psxCounters[3].mode; + psxCounters[3].mode&= ~0x1800; + psxCounters[3].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u16)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = psxCounters[4].mode; + psxCounters[4].mode&= ~0x1800; + psxCounters[4].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u16)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = psxCounters[5].mode; + psxCounters[5].mode&= ~0x1800; + psxCounters[5].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read16: %lx\n", hard); +#endif + return hard; + + case 0x1f801504: + hard = psxHu16(0x1504); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit read %lx\n", hard); +#endif + return hard; + case 0x1f801506: + hard = psxHu16(0x1506); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit read %lx\n", hard); +#endif + return hard; + //case 0x1f802030: hard = //int_2000???? + //case 0x1f802040: hard =//dip switches...?? + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + hard = SPU2read(add); + } else { + hard = psxHu16(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 16bit read at address %lx\n", add); +#endif + } + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +void psxConstReadCounterMode16(int x86reg, int index, int sign) +{ + if( IS_MMXREG(x86reg) ) { + MOV16MtoR(ECX, (u32)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (u32)&psxCounters[index].mode - 2); + } + else { + if( sign ) MOVSX32M16toR(ECX, (u32)&psxCounters[index].mode); + else MOVZX32M16toR(ECX, (u32)&psxCounters[index].mode); + + MOV32RtoR(x86reg, ECX); + } + + AND16ItoR(ECX, ~0x1800); + OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign) { + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD16_CALL(USBread16); + return 1; + } + + switch (add) { + + case 0x1f801040: + iFlushCall(0); + CALLFunc((u32)sioRead8); + PUSH32R(EAX); + CALLFunc((u32)sioRead8); + POP32R(ECX); + AND32ItoR(ECX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoR(EAX, ECX); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f801044: + _eeReadConstMem16(x86reg, (u32)&sio.StatReg, sign); + return 0; + + case 0x1f801048: + _eeReadConstMem16(x86reg, (u32)&sio.ModeReg, sign); + return 0; + + case 0x1f80104a: + _eeReadConstMem16(x86reg, (u32)&sio.CtrlReg, sign); + return 0; + + case 0x1f80104e: + _eeReadConstMem16(x86reg, (u32)&sio.BaudReg, sign); + return 0; + + // counters[0] + case 0x1f801100: + PUSH32I(0); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode16(x86reg, 0, sign); + return 0; + + case 0x1f801108: + _eeReadConstMem16(x86reg, (u32)&psxCounters[0].target, sign); + return 0; + + // counters[1] + case 0x1f801110: + PUSH32I(1); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode16(x86reg, 1, sign); + return 0; + + case 0x1f801118: + _eeReadConstMem16(x86reg, (u32)&psxCounters[1].target, sign); + return 0; + + // counters[2] + case 0x1f801120: + PUSH32I(2); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode16(x86reg, 2, sign); + return 0; + + case 0x1f801128: + _eeReadConstMem16(x86reg, (u32)&psxCounters[2].target, sign); + return 0; + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD16_CALL(DEV9read16); + return 1; + + // counters[3] + case 0x1f801480: + PUSH32I(3); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode16(x86reg, 3, sign); + return 0; + + case 0x1f801488: + _eeReadConstMem16(x86reg, (u32)&psxCounters[3].target, sign); + return 0; + + // counters[4] + case 0x1f801490: + PUSH32I(4); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode16(x86reg, 4, sign); + return 0; + + case 0x1f801498: + _eeReadConstMem16(x86reg, (u32)&psxCounters[4].target, sign); + return 0; + + // counters[5] + case 0x1f8014a0: + PUSH32I(5); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode16(x86reg, 5, sign); + return 0; + + case 0x1f8014a8: + _eeReadConstMem16(x86reg, (u32)&psxCounters[5].target, sign); + return 0; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + + PUSH32I(add); + CONSTREAD16_CALL(SPU2read); + return 1; + } else { + _eeReadConstMem16(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; + } + } +} + +u32 psxHwRead32(u32 add) { + u32 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread32(add); + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + return FWread32(add); + } + + switch (add) { + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; + hard|= sioRead8() << 16; + hard|= sioRead8() << 24; +#ifdef PAD_LOG + PAD_LOG("sio read32 ;ret = %lx\n", hard); +#endif + return hard; + + // case 0x1f801050: hard = serial_read32(); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size read %lx\n", psxHu32(0x1060)); + return psxHu32(0x1060); +#endif +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070)); + return psxHu32(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074)); + return psxHu32(0x1074); +#endif + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + hard = psxHu32(0x1078); + psxHu32(0x1078) = 0; + return hard; + +/* case 0x1f801810: +// hard = GPU_readData(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit read %lx\n", hard); +#endif + return hard;*/ +/* case 0x1f801814: + hard = GPU_readStatus(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit read %lx\n", hard); +#endif + return hard; +*/ +/* case 0x1f801820: hard = mdecRead0(); break; + case 0x1f801824: hard = mdecRead1(); break; +*/ +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit read %lx\n", psxHu32(0x10a0)); + return HW_DMA2_MADR; + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit read %lx\n", psxHu32(0x10a4)); + return HW_DMA2_BCR; + case 0x1f8010a8: + PSXHW_LOG("DMA2 CHCR 32bit read %lx\n", psxHu32(0x10a8)); + return HW_DMA2_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit read %lx\n", psxHu32(0x10b0)); + return HW_DMA3_MADR; + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit read %lx\n", psxHu32(0x10b4)); + return HW_DMA3_BCR; + case 0x1f8010b8: + PSXHW_LOG("DMA3 CHCR 32bit read %lx\n", psxHu32(0x10b8)); + return HW_DMA3_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit read %lx\n", HW_DMA9_MADR); + return HW_DMA9_MADR; + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit read %lx\n", HW_DMA9_BCR); + return HW_DMA9_BCR; + case 0x1f801528: + PSXHW_LOG("DMA9 CHCR 32bit read %lx\n", HW_DMA9_CHCR); + return HW_DMA9_CHCR; + case 0x1f80152C: + PSXHW_LOG("DMA9 TADR 32bit read %lx\n", HW_DMA9_TADR); + return HW_DMA9_TADR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit read %lx\n", HW_DMA10_MADR); + return HW_DMA10_MADR; + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit read %lx\n", HW_DMA10_BCR); + return HW_DMA10_BCR; + case 0x1f801538: + PSXHW_LOG("DMA10 CHCR 32bit read %lx\n", HW_DMA10_CHCR); + return HW_DMA10_CHCR; +#endif + +// case 0x1f8010f0: PSXHW_LOG("DMA PCR 32bit read " << psxHu32(0x10f0)); +// return HW_DMA_PCR; // dma rest channel +#ifdef PSXHW_LOG + case 0x1f8010f4: + PSXHW_LOG("DMA ICR 32bit read %lx\n", HW_DMA_ICR); + return HW_DMA_ICR; +#endif +//SSBus registers + case 0x1f801000: + hard = psxHu32(0x1000); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801004: + hard = psxHu32(0x1004); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8 (T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801008: + hard = psxHu32(0x1008); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80100C: + hard = psxHu32(0x100C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout (T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801010: + hard = psxHu32(0x1010); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS GIF(SIF2) (T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801014: + hard = psxHu32(0x1014); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T1) spu_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801018: + hard = psxHu32(0x1018); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80101C: + hard = psxHu32(0x101C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801020: + hard = psxHu32(0x1020); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS Config 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801400: + hard = psxHu32(0x1400); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801404: + hard = psxHu32(0x1404); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801408: + hard = psxHu32(0x1408); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80140C: + hard = psxHu32(0x140C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801410: + hard = psxHu32(0x1410); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801414: + hard = psxHu32(0x1414); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801418: + hard = psxHu32(0x1418); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF1(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80141C: + hard = psxHu32(0x141C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801420: + hard = psxHu32(0x1420); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2out(T1) 32bit read %lx\n", hard); +#endif + return hard; + + case 0x1f8010f0: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR 32bit read %lx\n", HW_DMA_PCR); +#endif + return HW_DMA_PCR; + + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit read %lx\n", HW_DMA4_CHCR); +#endif + return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA) + + // time for rootcounters :) + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801104: + hard = (u16)psxCounters[0].mode; + psxCounters[0].mode&= ~0x1800; + psxCounters[0].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801114: + hard = (u16)psxCounters[1].mode; + psxCounters[1].mode&= ~0x1800; + psxCounters[1].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801124: + hard = (u16)psxCounters[2].mode; + psxCounters[2].mode&= ~0x1800; + psxCounters[2].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801480: + hard = (u32)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = (u16)psxCounters[3].mode; + psxCounters[3].mode&= ~0x1800; + psxCounters[3].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u32)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = (u16)psxCounters[4].mode; + psxCounters[4].mode&= ~0x1800; + psxCounters[4].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u32)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = (u16)psxCounters[5].mode; + psxCounters[5].mode&= ~0x1800; + psxCounters[5].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801450: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("%08X ICFG 32bit read %x\n", psxRegs.pc, hard); +#endif + return hard; + + + case 0x1f801500: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 MADR 32bit read %lx\n", HW_DMA7_MADR); +#endif + return HW_DMA7_MADR; // DMA7 madr + case 0x1f801504: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR 32bit read %lx\n", HW_DMA7_BCR); +#endif + return HW_DMA7_BCR; // DMA7 bcr + + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit read %lx\n", HW_DMA7_CHCR); +#endif + return HW_DMA7_CHCR; // DMA7 chcr (SPU2) + + case 0x1f801570: + hard = psxHu32(0x1570); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit read %lx\n", hard); +#endif + return hard; +#ifdef PSXHW_LOG + case 0x1f801574: + PSXHW_LOG("DMA ICR2 32bit read %lx\n", HW_DMA_ICR2); + return HW_DMA_ICR2; +#endif + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + hard=sio2_getSend3((add-0x1F808200)/4); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read param[%d] (%lx)\n", (add-0x1F808200)/4, hard); +#endif + return hard; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + hard=sio2_getSend1((add-0x1F808240)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send1[%d] (%lx)\n", (add-0x1F808240)/8, hard); +#endif + return hard; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + hard=sio2_getSend2((add-0x1F808244)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send2[%d] (%lx)\n", (add-0x1F808244)/8, hard); +#endif + return hard; + + case 0x1F808268: + hard=sio2_getCtrl(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read CTRL (%lx)\n", hard); +#endif + return hard; + + case 0x1F80826C: + hard=sio2_getRecv1(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv1 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808270: + hard=sio2_getRecv2(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv2 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808274: + hard=sio2_getRecv3(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv3 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808278: + hard=sio2_get8278(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [8278] (%lx)\n", hard); +#endif + return hard; + + case 0x1F80827C: + hard=sio2_get827C(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [827C] (%lx)\n", hard); +#endif + return hard; + + case 0x1F808280: + hard=sio2_getIntr(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read INTR (%lx)\n", hard); +#endif + return hard; + + default: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; +} + +void psxConstReadCounterMode32(int x86reg, int index) +{ + if( IS_MMXREG(x86reg) ) { + MOV16MtoR(ECX, (u32)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (u32)&psxCounters[index].mode); + } + else { + MOVZX32M16toR(ECX, (u32)&psxCounters[index].mode); + MOV32RtoR(x86reg, ECX); + } + + AND16ItoR(ECX, ~0x1800); + OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +static u32 s_tempsio; +int psxHwConstRead32(u32 x86reg, u32 add) { + if (add >= 0x1f801600 && add < 0x1f801700) { + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBread32); + return 1; + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)FWread32); + return 1; + } + + switch (add) { + case 0x1f801040: + iFlushCall(0); + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&s_tempsio, EAX); + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoM((u32)&s_tempsio, EAX); + + // 3rd + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 16); + OR32RtoM((u32)&s_tempsio, EAX); + + // 4th + CALLFunc((u32)sioRead8); + SHL32ItoR(EAX, 24); + OR32MtoR(EAX, (u32)&s_tempsio); + return 1; + + //case 0x1f801050: hard = serial_read32(); break;//serial port + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + _eeReadConstMem32(x86reg, (u32)&psxH[add&0xffff]); + MOV32ItoM((u32)&psxH[add&0xffff], 0); + return 0; + + // counters[0] + case 0x1f801100: + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode32(x86reg, 0); + return 0; + + case 0x1f801108: + _eeReadConstMem32(x86reg, (u32)&psxCounters[0].target); + return 0; + + // counters[1] + case 0x1f801110: + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode32(x86reg, 1); + return 0; + + case 0x1f801118: + _eeReadConstMem32(x86reg, (u32)&psxCounters[1].target); + return 0; + + // counters[2] + case 0x1f801120: + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode32(x86reg, 2); + return 0; + + case 0x1f801128: + _eeReadConstMem32(x86reg, (u32)&psxCounters[2].target); + return 0; + + // counters[3] + case 0x1f801480: + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode32(x86reg, 3); + return 0; + + case 0x1f801488: + _eeReadConstMem32(x86reg, (u32)&psxCounters[3].target); + return 0; + + // counters[4] + case 0x1f801490: + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode32(x86reg, 4); + return 0; + + case 0x1f801498: + _eeReadConstMem32(x86reg, (u32)&psxCounters[4].target); + return 0; + + // counters[5] + case 0x1f8014a0: + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode32(x86reg, 5); + return 0; + + case 0x1f8014a8: + _eeReadConstMem32(x86reg, (u32)&psxCounters[5].target); + return 0; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((u32)sio2_getSend3); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((u32)sio2_getSend1); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((u32)sio2_getSend2); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808268: + iFlushCall(0); + CALLFunc((u32)sio2_getCtrl); + return 1; + + case 0x1F80826C: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv1); + return 1; + + case 0x1F808270: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv2); + return 1; + + case 0x1F808274: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv3); + return 1; + + case 0x1F808278: + iFlushCall(0); + CALLFunc((u32)sio2_get8278); + return 1; + + case 0x1F80827C: + iFlushCall(0); + CALLFunc((u32)sio2_get827C); + return 1; + + case 0x1F808280: + iFlushCall(0); + CALLFunc((u32)sio2_getIntr); + return 1; + + default: + _eeReadConstMem32(x86reg, (u32)&psxH[(add) & 0xffff]); + return 0; + } +} + +static int pbufi; +static s8 pbuf[1024]; + +#define DmaExec(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite8(u32 add, u8 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite8(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0xa) SysPrintf("8bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: sioWrite8(value); break; + // case 0x1f801050: serial_write8(value); break;//serial port + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 8bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu8(0x1450) = value; + return; + + case 0x1f801800: cdrWrite0(value); break; + case 0x1f801801: cdrWrite1(value); break; + case 0x1f801802: cdrWrite2(value); break; + case 0x1f801803: cdrWrite3(value); break; + + case 0x1f80380c: + if (value == '\r') break; + if (value == '\n' || pbufi >= 1023) { + pbuf[pbufi++] = 0; pbufi = 0; + SysPrintf("%s\n", pbuf); break; + } + pbuf[pbufi++] = value; + break; + + case 0x1F808260: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write8 DATAIN <- %08X\n", value); +#endif + sio2_fifoIn(value);return;//serial data feed/fifo + + default: + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +#define CONSTWRITE_CALL(name) { \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void Write8PrintBuffer(u8 value) +{ + if (value == '\r') return; + if (value == '\n' || pbufi >= 1023) { + pbuf[pbufi++] = 0; pbufi = 0; + SysPrintf("%s\n", pbuf); return; + } + pbuf[pbufi++] = value; +} + +void psxHwConstWrite8(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite8); + return; + } + + switch (add) { + case 0x1f801040: + CONSTWRITE_CALL(sioWrite8); break; + //case 0x1f801050: serial_write8(value); break;//serial port + + case 0x1f801800: CONSTWRITE_CALL(cdrWrite0); break; + case 0x1f801801: CONSTWRITE_CALL(cdrWrite1); break; + case 0x1f801802: CONSTWRITE_CALL(cdrWrite2); break; + case 0x1f801803: CONSTWRITE_CALL(cdrWrite3); break; + case 0x1f80380c: CONSTWRITE_CALL(Write8PrintBuffer); break; + case 0x1F808260: CONSTWRITE_CALL(sio2_fifoIn); break; + + default: + _eeWriteConstMem8((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +void psxHwWrite16(u32 add, u16 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite16(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)(value>>8)); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801044: +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801048: + sio.ModeReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104a: // control register + sioWriteCtrl16(value); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104e: // baudrate register + sio.BaudReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + + //serial port ;P + // case 0x1f801050: serial_write16(value); break; + // case 0x1f80105a: serial_control_write(value);break; + // case 0x1f80105e: serial_baud_write(value); break; + // case 0x1f801054: serial_status_write(value); break; + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 16bit write %x\n", value); +#endif +// if (Config.Sio) psxHu16(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu16(0x1070) |= 0x200; + psxHu16(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value); + psxHu16(0x1074) = value; + return; +#endif + + case 0x1f8010c4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value); +#endif + psxHu16(0x10c4) = value; return; // DMA4 bcr_size + + case 0x1f8010c6: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value); +#endif + psxHu16(0x10c6) = value; return; // DMA4 bcr_count + + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(0, value); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(0, value); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(1, value); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(1, value); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(2, value); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 16bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu16(0x1450) = value/* & (~0x8)*/; + return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 16bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 16bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 16bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f801504: + psxHu16(0x1504) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit write %lx\n", value); +#endif + return; + case 0x1f801506: + psxHu16(0x1506) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit write %lx\n", value); +#endif + return; + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + SPU2write(add, value); + return; + } + + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 16bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHwConstWrite16(u32 add, int mmreg) { + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite16); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 3); + return; + case 0x1f801044: + return; + case 0x1f801048: + _eeWriteConstMem16((u32)&sio.ModeReg, mmreg); + return; + case 0x1f80104a: // control register + CONSTWRITE_CALL(sioWriteCtrl16); + return; + case 0x1f80104e: // baudrate register + _eeWriteConstMem16((u32)&sio.BaudReg, mmreg); + return; + + case 0x1f801070: + _eeWriteConstMem16OP((u32)&psxH[(add) & 0xffff], mmreg, 0); + return; + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)SPU2write); + // leave esp alone + return; + } + + _eeWriteConstMem16((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +#define DmaExec2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite32(u32 add, u32 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite32(add, value); return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + FWwrite32(add, value); return; + } + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)((value&0xff) >> 8)); + sioWrite8((u8)((value&0xff) >> 16)); + sioWrite8((u8)((value&0xff) >> 24)); +#ifdef PAD_LOG + PAD_LOG("sio write32 %lx\n", value); +#endif + return; + // case 0x1f801050: serial_write32(value); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size write %lx\n", value); + psxHu32(add) = value; + return; // Ram size +#endif + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 32bit write %lx\n", value); +#endif +// if (Config.Sio) psxHu32(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu32(0x1070) |= 0x200; + psxHu32(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: + PSXHW_LOG("IMASK 32bit write %lx\n", value); + psxHu32(0x1074) = value; + return; + + case 0x1f801078: + PSXHW_LOG("ICTRL 32bit write %lx\n", value); +// SysPrintf("ICTRL 32bit write %lx\n", value); + psxHu32(0x1078) = value; + return; +#endif + + //SSBus registers + case 0x1f801000: + psxHu32(0x1000) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801004: + psxHu32(0x1004) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8 (T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801008: + psxHu32(0x1008) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f80100C: + psxHu32(0x100C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout (T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801010: + psxHu32(0x1010) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS GIF(SIF2) (T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801014: + psxHu32(0x1014) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T1) spu_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801018: + psxHu32(0x1018) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f80101C: + psxHu32(0x101C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801020: + psxHu32(0x1020) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS Config 32bit write %lx\n", value); +#endif + return; + case 0x1f801400: + psxHu32(0x1400) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801404: + psxHu32(0x1404) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801408: + psxHu32(0x1408) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f80140C: + psxHu32(0x140C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801410: + psxHu32(0x1410) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801414: + psxHu32(0x1414) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801418: + psxHu32(0x1418) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF1(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f80141C: + psxHu32(0x141C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801420: + psxHu32(0x1420) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2out(T1) 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f801080: + PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); + HW_DMA0_MADR = value; return; // DMA0 madr + case 0x1f801084: + PSXHW_LOG("DMA0 BCR 32bit write %lx\n", value); + HW_DMA0_BCR = value; return; // DMA0 bcr +#endif + case 0x1f801088: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA0 CHCR 32bit write %lx\n", value); +#endif + HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +// DmaExec(0); + return; + +#ifdef PSXHW_LOG + case 0x1f801090: + PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); + HW_DMA1_MADR = value; return; // DMA1 madr + case 0x1f801094: + PSXHW_LOG("DMA1 BCR 32bit write %lx\n", value); + HW_DMA1_BCR = value; return; // DMA1 bcr +#endif + case 0x1f801098: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA1 CHCR 32bit write %lx\n", value); +#endif + HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +// DmaExec(1); + return; + +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); + HW_DMA2_MADR = value; return; // DMA2 madr + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit write %lx\n", value); + HW_DMA2_BCR = value; return; // DMA2 bcr +#endif + case 0x1f8010a8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA2 CHCR 32bit write %lx\n", value); +#endif + HW_DMA2_CHCR = value; // DMA2 chcr (GPU DMA) + DmaExec(2); + return; + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); + HW_DMA3_MADR = value; return; // DMA3 madr + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit write %lx\n", value); + HW_DMA3_BCR = value; return; // DMA3 bcr +#endif + case 0x1f8010b8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA3 CHCR 32bit write %lx\n", value); +#endif + HW_DMA3_CHCR = value; // DMA3 chcr (CDROM DMA) + DmaExec(3); + + return; + +#ifdef PSXHW_LOG + case 0x1f8010c0: + PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); + HW_DMA4_MADR = value; return; // DMA4 madr + case 0x1f8010c4: + PSXHW_LOG("DMA4 BCR 32bit write %lx\n", value); + HW_DMA4_BCR = value; return; // DMA4 bcr +#endif + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit write %lx\n", value); +#endif + HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA) + DmaExec(4); + return; + +#if 0 + case 0x1f8010d0: break; //DMA5write_madr(); + case 0x1f8010d4: break; //DMA5write_bcr(); + case 0x1f8010d8: break; //DMA5write_chcr(); // Not yet needed?? +#endif + +#ifdef PSXHW_LOG + case 0x1f8010e0: + PSXHW_LOG("DMA6 MADR 32bit write %lx\n", value); + HW_DMA6_MADR = value; return; // DMA6 madr + case 0x1f8010e4: + PSXHW_LOG("DMA6 BCR 32bit write %lx\n", value); + HW_DMA6_BCR = value; return; // DMA6 bcr +#endif + case 0x1f8010e8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA6 CHCR 32bit write %lx\n", value); +#endif + HW_DMA6_CHCR = value; // DMA6 chcr (OT clear) + DmaExec(6); + return; + +#ifdef PSXHW_LOG + case 0x1f801500: + PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value); + HW_DMA7_MADR = value; return; // DMA7 madr + case 0x1f801504: + PSXHW_LOG("DMA7 BCR 32bit write %lx\n", value); + HW_DMA7_BCR = value; return; // DMA7 bcr +#endif + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit write %lx\n", value); +#endif + HW_DMA7_CHCR = value; // DMA7 chcr (SPU2) + DmaExec2(7); + return; + +#ifdef PSXHW_LOG + case 0x1f801510: + PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value); + HW_DMA8_MADR = value; return; // DMA8 madr + case 0x1f801514: + PSXHW_LOG("DMA8 BCR 32bit write %lx\n", value); + HW_DMA8_BCR = value; return; // DMA8 bcr +#endif + case 0x1f801518: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA8 CHCR 32bit write %lx\n", value); +#endif + HW_DMA8_CHCR = value; // DMA8 chcr (DEV9) + DmaExec2(8); + return; + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value); + HW_DMA9_MADR = value; return; // DMA9 madr + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit write %lx\n", value); + HW_DMA9_BCR = value; return; // DMA9 bcr +#endif + case 0x1f801528: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA9 CHCR 32bit write %lx\n", value); +#endif + HW_DMA9_CHCR = value; // DMA9 chcr (SIF0) + DmaExec2(9); + return; +#ifdef PSXHW_LOG + case 0x1f80152c: + PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value); + HW_DMA9_TADR = value; return; // DMA9 tadr +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value); + HW_DMA10_MADR = value; return; // DMA10 madr + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit write %lx\n", value); + HW_DMA10_BCR = value; return; // DMA10 bcr +#endif + case 0x1f801538: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA10 CHCR 32bit write %lx\n", value); +#endif + HW_DMA10_CHCR = value; // DMA10 chcr (SIF1) + DmaExec2(10); + return; + +#ifdef PSXHW_LOG + case 0x1f801540: + PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value); + HW_DMA11_MADR = value; return; + + case 0x1f801544: + PSXHW_LOG("DMA11 SIO2in BCR 32bit write %lx\n", value); + HW_DMA11_BCR = value; return; +#endif + case 0x1f801548: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA11 SIO2in CHCR 32bit write %lx\n", value); +#endif + HW_DMA11_CHCR = value; // DMA11 chcr (SIO2 in) + DmaExec2(11); + return; + +#ifdef PSXHW_LOG + case 0x1f801550: + PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value); + HW_DMA12_MADR = value; return; + + case 0x1f801554: + PSXHW_LOG("DMA12 SIO2out BCR 32bit write %lx\n", value); + HW_DMA12_BCR = value; return; +#endif + case 0x1f801558: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA12 SIO2out CHCR 32bit write %lx\n", value); +#endif + HW_DMA12_CHCR = value; // DMA12 chcr (SIO2 out) + DmaExec2(12); + return; + + case 0x1f801570: + psxHu32(0x1570) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f8010f0: + PSXHW_LOG("DMA PCR 32bit write %lx\n", value); + HW_DMA_PCR = value; + return; +#endif + + case 0x1f8010f4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR; + HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + + case 0x1f801574: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR2 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR2; + HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + +/* case 0x1f801810: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit write %lx\n", value); +#endif + GPU_writeData(value); return; + case 0x1f801814: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit write %lx\n", value); +#endif + GPU_writeStatus(value); return; +*/ +/* case 0x1f801820: + mdecWrite0(value); break; + case 0x1f801824: + mdecWrite1(value); break; +*/ + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(0, value ); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 32bit write %lx\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(0, value ); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(1, value ); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 32bit write %lx\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(1, value ); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(2, value ); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 32bit write %lx\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 32bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 32bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 32bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f8014c0: +#ifdef PSXHW_LOG + PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value); +#endif + SysPrintf("RTC_HOLDMODE 32bit write %lx\n", value); + break; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 32bit write %lx\n", psxRegs.pc, value); } +#endif +/* if (value && + psxSu32(0x20) == 0x20000 && + (psxSu32(0x30) == 0x20000 || + psxSu32(0x30) == 0x40000)) { // don't ask me why :P + psxSu32(0x20) = 0x10000; + psxSu32(0x30) = 0x10000; + }*/ + psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/; + return; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write param[%d] <- %lx\n", (add-0x1F808200)/4, value); +#endif + sio2_setSend3((add-0x1F808200)/4, value); return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send1[%d] <- %lx\n", (add-0x1F808240)/8, value); +#endif + sio2_setSend1((add-0x1F808240)/8, value); return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send2[%d] <- %lx\n", (add-0x1F808244)/8, value); +#endif + sio2_setSend2((add-0x1F808244)/8, value); return; + + case 0x1F808268: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write CTRL <- %lx\n", value); +#endif + sio2_setCtrl(value); return; + + case 0x1F808278: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [8278] <- %lx\n", value); +#endif + sio2_set8278(value); return; + + case 0x1F80827C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [827C] <- %lx\n", value); +#endif + sio2_set827C(value); return; + + case 0x1F808280: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write INTR <- %lx\n", value); +#endif + sio2_setIntr(value); return; + + default: + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value); +#endif + return; + } + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit write at address %lx value %lx\n", add, value); +#endif +} + +#define recDmaExec(n) { \ + iFlushCall(0); \ + if( n > 6 ) \ + TEST32ItoM((u32)&HW_DMA_PCR2, 8 << ((n-7) * 4)); \ + else \ + TEST32ItoM((u32)&HW_DMA_PCR, 8 << (n * 4)); \ + j8Ptr[5] = JZ8(0); \ + MOV32MtoR(EAX, (u32)&HW_DMA##n##_CHCR); \ + TEST32ItoR(EAX, 0x01000000); \ + j8Ptr[6] = JZ8(0); \ + \ + PUSH32R(EAX); \ + PUSH32M((u32)&HW_DMA##n##_BCR); \ + PUSH32M((u32)&HW_DMA##n##_MADR); \ + CALLFunc((u32)psxDma##n); \ + ADD32ItoR(ESP, 12); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ +} \ + +#define CONSTWRITE_CALL32(name) { \ + iFlushCall(0); \ + _recPushReg(mmreg); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void psxHwConstWrite32(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite32); + return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)FWwrite32); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + return; + + case 0x1f801070: + _eeWriteConstMem32OP((u32)&psxH[(add) & 0xffff], mmreg, 0); // and + return; + +// case 0x1f801088: +// HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +//// DmaExec(0); +// return; + +// case 0x1f801098: +// HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +//// DmaExec(1); +// return; + + case 0x1f8010a8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(2); + return; + + case 0x1f8010b8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(3); + return; + + case 0x1f8010c8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(4); + return; + + case 0x1f8010e8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(6); + return; + + case 0x1f801508: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(7); + return; + + case 0x1f801518: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(8); + return; + + case 0x1f801528: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(9); + return; + + case 0x1f801538: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(10); + return; + + case 0x1f801548: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(11); + return; + + case 0x1f801558: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(12); + return; + + case 0x1f8010f4: + case 0x1f801574: + { + // u32 tmp = (~value) & HW_DMA_ICR; + _eeMoveMMREGtoR(EAX, mmreg); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND32MtoR(ECX, (u32)&psxH[(add) & 0xffff]); + + // HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + XOR32RtoR(EAX, ECX); + AND32ItoR(EAX, 0xffffff); + XOR32RtoR(EAX, ECX); + MOV32RtoM((u32)&psxH[(add) & 0xffff], EAX); + return; + } + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL32(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL32(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL32(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL32(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL32(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL32(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014c0: + SysPrintf("RTC_HOLDMODE 32bit write\n"); + break; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((u32)sio2_setSend3); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((u32)sio2_setSend1); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((u32)sio2_setSend2); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808268: CONSTWRITE_CALL32(sio2_setCtrl); return; + case 0x1F808278: CONSTWRITE_CALL32(sio2_set8278); return; + case 0x1F80827C: CONSTWRITE_CALL32(sio2_set827C); return; + case 0x1F808280: CONSTWRITE_CALL32(sio2_setIntr); return; + + default: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +u8 psxHw4Read8(u32 add) { + u8 hard; + + switch (add) { + case 0x1f402004: return cdvdRead04(); + case 0x1f402005: return cdvdRead05(); + case 0x1f402006: return cdvdRead06(); + case 0x1f402007: return cdvdRead07(); + case 0x1f402008: return cdvdRead08(); + case 0x1f40200A: return cdvdRead0A(); + case 0x1f40200B: return cdvdRead0B(); + case 0x1f40200C: return cdvdRead0C(); + case 0x1f40200D: return cdvdRead0D(); + case 0x1f40200E: return cdvdRead0E(); + case 0x1f40200F: return cdvdRead0F(); + case 0x1f402013: return cdvdRead13(); + case 0x1f402015: return cdvdRead15(); + case 0x1f402016: return cdvdRead16(); + case 0x1f402017: return cdvdRead17(); + case 0x1f402018: return cdvdRead18(); + case 0x1f402020: return cdvdRead20(); + case 0x1f402021: return cdvdRead21(); + case 0x1f402022: return cdvdRead22(); + case 0x1f402023: return cdvdRead23(); + case 0x1f402024: return cdvdRead24(); + case 0x1f402028: return cdvdRead28(); + case 0x1f402029: return cdvdRead29(); + case 0x1f40202A: return cdvdRead2A(); + case 0x1f40202B: return cdvdRead2B(); + case 0x1f40202C: return cdvdRead2C(); + case 0x1f402030: return cdvdRead30(); + case 0x1f402031: return cdvdRead31(); + case 0x1f402032: return cdvdRead32(); + case 0x1f402033: return cdvdRead33(); + case 0x1f402034: return cdvdRead34(); + case 0x1f402038: return cdvdRead38(); + case 0x1f402039: return cdvdRead39(); + case 0x1f40203A: return cdvdRead3A(); + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + return 0; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + + return hard; +} + +int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) { + switch (add) { + case 0x1f402004: CONSTREAD8_CALL((u32)cdvdRead04); return 1; + case 0x1f402005: CONSTREAD8_CALL((u32)cdvdRead05); return 1; + case 0x1f402006: CONSTREAD8_CALL((u32)cdvdRead06); return 1; + case 0x1f402007: CONSTREAD8_CALL((u32)cdvdRead07); return 1; + case 0x1f402008: CONSTREAD8_CALL((u32)cdvdRead08); return 1; + case 0x1f40200A: CONSTREAD8_CALL((u32)cdvdRead0A); return 1; + case 0x1f40200B: CONSTREAD8_CALL((u32)cdvdRead0B); return 1; + case 0x1f40200C: CONSTREAD8_CALL((u32)cdvdRead0C); return 1; + case 0x1f40200D: CONSTREAD8_CALL((u32)cdvdRead0D); return 1; + case 0x1f40200E: CONSTREAD8_CALL((u32)cdvdRead0E); return 1; + case 0x1f40200F: CONSTREAD8_CALL((u32)cdvdRead0F); return 1; + case 0x1f402013: CONSTREAD8_CALL((u32)cdvdRead13); return 1; + case 0x1f402015: CONSTREAD8_CALL((u32)cdvdRead15); return 1; + case 0x1f402016: CONSTREAD8_CALL((u32)cdvdRead16); return 1; + case 0x1f402017: CONSTREAD8_CALL((u32)cdvdRead17); return 1; + case 0x1f402018: CONSTREAD8_CALL((u32)cdvdRead18); return 1; + case 0x1f402020: CONSTREAD8_CALL((u32)cdvdRead20); return 1; + case 0x1f402021: CONSTREAD8_CALL((u32)cdvdRead21); return 1; + case 0x1f402022: CONSTREAD8_CALL((u32)cdvdRead22); return 1; + case 0x1f402023: CONSTREAD8_CALL((u32)cdvdRead23); return 1; + case 0x1f402024: CONSTREAD8_CALL((u32)cdvdRead24); return 1; + case 0x1f402028: CONSTREAD8_CALL((u32)cdvdRead28); return 1; + case 0x1f402029: CONSTREAD8_CALL((u32)cdvdRead29); return 1; + case 0x1f40202A: CONSTREAD8_CALL((u32)cdvdRead2A); return 1; + case 0x1f40202B: CONSTREAD8_CALL((u32)cdvdRead2B); return 1; + case 0x1f40202C: CONSTREAD8_CALL((u32)cdvdRead2C); return 1; + case 0x1f402030: CONSTREAD8_CALL((u32)cdvdRead30); return 1; + case 0x1f402031: CONSTREAD8_CALL((u32)cdvdRead31); return 1; + case 0x1f402032: CONSTREAD8_CALL((u32)cdvdRead32); return 1; + case 0x1f402033: CONSTREAD8_CALL((u32)cdvdRead33); return 1; + case 0x1f402034: CONSTREAD8_CALL((u32)cdvdRead34); return 1; + case 0x1f402038: CONSTREAD8_CALL((u32)cdvdRead38); return 1; + case 0x1f402039: CONSTREAD8_CALL((u32)cdvdRead39); return 1; + case 0x1f40203A: CONSTREAD8_CALL((u32)cdvdRead3A); return 1; + default: + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + XOR32RtoR(x86reg, x86reg); + return 0; + } +} + +void psxHw4Write8(u32 add, u8 value) { + switch (add) { + case 0x1f402004: cdvdWrite04(value); return; + case 0x1f402005: cdvdWrite05(value); return; + case 0x1f402006: cdvdWrite06(value); return; + case 0x1f402007: cdvdWrite07(value); return; + case 0x1f402008: cdvdWrite08(value); return; + case 0x1f40200A: cdvdWrite0A(value); return; + case 0x1f40200F: cdvdWrite0F(value); return; + case 0x1f402014: cdvdWrite14(value); return; + case 0x1f402016: + cdvdWrite16(value); + FreezeMMXRegs(0); + return; + case 0x1f402017: cdvdWrite17(value); return; + case 0x1f402018: cdvdWrite18(value); return; + case 0x1f40203A: cdvdWrite3A(value); return; + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + SysPrintf("*Unknown 8bit write at address %lx value %x\n", add, value); + return; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHw4ConstWrite8(u32 add, int mmreg) { + switch (add) { + case 0x1f402004: CONSTWRITE_CALL(cdvdWrite04); return; + case 0x1f402005: CONSTWRITE_CALL(cdvdWrite05); return; + case 0x1f402006: CONSTWRITE_CALL(cdvdWrite06); return; + case 0x1f402007: CONSTWRITE_CALL(cdvdWrite07); return; + case 0x1f402008: CONSTWRITE_CALL(cdvdWrite08); return; + case 0x1f40200A: CONSTWRITE_CALL(cdvdWrite0A); return; + case 0x1f40200F: CONSTWRITE_CALL(cdvdWrite0F); return; + case 0x1f402014: CONSTWRITE_CALL(cdvdWrite14); return; + case 0x1f402016: + _freeMMXregs(); + CONSTWRITE_CALL(cdvdWrite16); + return; + case 0x1f402017: CONSTWRITE_CALL(cdvdWrite17); return; + case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return; + case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return; + default: + SysPrintf("*Unknown 8bit write at address %lx\n", add); + return; + } +} + +void psxDmaInterrupt(int n) { + if (HW_DMA_ICR & (1 << (16 + n))) { + HW_DMA_ICR|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (9 + n); + psxHu32(0x1070) |= 8; + //hwIntcIrq(INTC_SBUS); + + } +} + +void psxDmaInterrupt2(int n) { + if (HW_DMA_ICR2 & (1 << (16 + n))) { +/* if (HW_DMA_ICR2 & (1 << (24 + n))) { + SysPrintf("*PCSX2*: HW_DMA_ICR2 n=%d already set\n", n); + } + if (psxHu32(0x1070) & 8) { + SysPrintf("*PCSX2*: psxHu32(0x1070) 8 already set (n=%d)\n", n); + }*/ + HW_DMA_ICR2|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (16 + n); + psxHu32(0x1070) |= 8; + //hwIntcIrq(INTC_SBUS); + } +} diff --git a/PsxHw.h b/PsxHw.h new file mode 100644 index 0000000000..c0f4b645a9 --- /dev/null +++ b/PsxHw.h @@ -0,0 +1,117 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXHW_H__ +#define __PSXHW_H__ + +#define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA +#define HW_DMA0_BCR (psxHu32(0x1084)) +#define HW_DMA0_CHCR (psxHu32(0x1088)) + +#define HW_DMA1_MADR (psxHu32(0x1090)) // MDEC out DMA +#define HW_DMA1_BCR (psxHu32(0x1094)) +#define HW_DMA1_CHCR (psxHu32(0x1098)) + +#define HW_DMA2_MADR (psxHu32(0x10a0)) // GPU DMA +#define HW_DMA2_BCR (psxHu32(0x10a4)) +#define HW_DMA2_CHCR (psxHu32(0x10a8)) +#define HW_DMA2_TADR (psxHu32(0x10ac)) + +#define HW_DMA3_MADR (psxHu32(0x10b0)) // CDROM DMA +#define HW_DMA3_BCR (psxHu32(0x10b4)) +#define HW_DMA3_BCR_L16 (psxHu16(0x10b4)) +#define HW_DMA3_BCR_H16 (psxHu16(0x10b6)) +#define HW_DMA3_CHCR (psxHu32(0x10b8)) + +#define HW_DMA4_MADR (psxHu32(0x10c0)) // SPU DMA +#define HW_DMA4_BCR (psxHu32(0x10c4)) +#define HW_DMA4_CHCR (psxHu32(0x10c8)) +#define HW_DMA4_TADR (psxHu32(0x10cc)) + +#define HW_DMA6_MADR (psxHu32(0x10e0)) // GPU DMA (OT) +#define HW_DMA6_BCR (psxHu32(0x10e4)) +#define HW_DMA6_CHCR (psxHu32(0x10e8)) + +#define HW_DMA7_MADR (psxHu32(0x1500)) // SPU2 DMA +#define HW_DMA7_BCR (psxHu32(0x1504)) +#define HW_DMA7_CHCR (psxHu32(0x1508)) + +#define HW_DMA8_MADR (psxHu32(0x1510)) // DEV9 DMA +#define HW_DMA8_BCR (psxHu32(0x1514)) +#define HW_DMA8_CHCR (psxHu32(0x1518)) + +#define HW_DMA9_MADR (psxHu32(0x1520)) // SIF0 DMA +#define HW_DMA9_BCR (psxHu32(0x1524)) +#define HW_DMA9_CHCR (psxHu32(0x1528)) +#define HW_DMA9_TADR (psxHu32(0x152c)) + +#define HW_DMA10_MADR (psxHu32(0x1530)) // SIF1 DMA +#define HW_DMA10_BCR (psxHu32(0x1534)) +#define HW_DMA10_CHCR (psxHu32(0x1538)) + +#define HW_DMA11_MADR (psxHu32(0x1540)) // SIO2 in +#define HW_DMA11_BCR (psxHu32(0x1544)) +#define HW_DMA11_CHCR (psxHu32(0x1548)) + +#define HW_DMA12_MADR (psxHu32(0x1550)) // SIO2 out +#define HW_DMA12_BCR (psxHu32(0x1554)) +#define HW_DMA12_CHCR (psxHu32(0x1558)) + +#define HW_DMA_PCR (psxHu32(0x10f0)) +#define HW_DMA_ICR (psxHu32(0x10f4)) + +#define HW_DMA_PCR2 (psxHu32(0x1570)) +#define HW_DMA_ICR2 (psxHu32(0x1574)) + +#define PSX_INT(n, ecycle) \ + psxRegs.interrupt|= 1 << n; \ + g_psxNextBranchCycle = min(g_psxNextBranchCycle, psxRegs.cycle+ecycle); \ + psxRegs.sCycle[n] = psxRegs.cycle; \ + psxRegs.eCycle[n] = ecycle; + + +void psxHwReset(); +u8 psxHwRead8 (u32 add); +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign); + +u16 psxHwRead16(u32 add); +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign); + +u32 psxHwRead32(u32 add); +int psxHwConstRead32(u32 x86reg, u32 add); + +void psxHwWrite8 (u32 add, u8 value); +void psxHwConstWrite8(u32 add, int mmreg); + +void psxHwWrite16(u32 add, u16 value); +void psxHwConstWrite16(u32 add, int mmreg); + +void psxHwWrite32(u32 add, u32 value); +void psxHwConstWrite32(u32 add, int mmreg); + +u8 psxHw4Read8 (u32 add); +int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign); + +void psxHw4Write8(u32 add, u8 value); +void psxHw4ConstWrite8(u32 add, int mmreg); + +int psxHwFreeze(gzFile f, int Mode); +void psxDmaInterrupt(int n); +void psxDmaInterrupt2(int n); + +#endif /* __PSXHW_H__ */ diff --git a/PsxInterpreter.c b/PsxInterpreter.c new file mode 100644 index 0000000000..ebd97390e2 --- /dev/null +++ b/PsxInterpreter.c @@ -0,0 +1,782 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +//#include "PsxBios2.h" + +static int branch = 0; +static int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef PSXCPU_LOG +#define debugI() \ + if (Log) { \ + PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); \ + } +#else +#define debugI() +#endif + +#define execI() { \ + psxRegs.code = PSXMu32(psxRegs.pc); \ + \ + debugI(); \ + psxRegs.pc+= 4; \ + psxRegs.cycle++; \ + \ + psxBSC[psxRegs.code >> 26](); \ + EEsCycle-= (psxRegs.cycle - IOPoCycle) << 3; \ + IOPoCycle = psxRegs.cycle; \ +} + +#define doBranch(tar) { \ + branch2 = branch = 1; \ + branchPC = tar; \ + execI(); \ + branch = 0; \ + psxRegs.pc = branchPC; \ + \ + psxBranchTest(); \ +} + +// Subsets +void (*psxBSC[64])(); +void (*psxSPC[64])(); +void (*psxREG[32])(); +void (*psxCP0[32])(); +void (*psxCP2[64])(); +void (*psxCP2BSC[32])(); + +extern void bios_write(); +extern void bios_printf(); + +typedef struct { + char name[8]; + char names[64][32]; + int maxn; +} irxlib; + +#define IRXLIBS 14 +irxlib irxlibs[32] = { +/*00*/ { { "sysmem" } , + { "start", "init_memory", "retonly", "return_addr_of_memsize", + "AllocSysMemory", "FreeSysMemory", "QueryMemSize", "QueryMaxFreeMemSize", + "QueryTotalFreeMemSize", "QueryBlockTopAddress", "QueryBlockSize", "retonly", + "retonly", "retonly", "Kprintf", "set_Kprintf" } , + 16 }, +/*01*/ { { "loadcore" } , + { "start", "retonly", "retonly_", "return_LibraryEntryTable", + "FlushIcache", "FlushDcache", "RegisterLibraryEntries", "ReleaseLibraryEntries", + "findFixImports", "restoreImports", "RegisterNonAutoLinkEntries", "QueryLibraryEntryTable", + "QueryBootMode", "RegisterBootMode", "setFlag", "resetFlag", + "linkModule", "unlinkModule", "retonly_", "retonly_", + "registerFunc", "jumpA0001B34", "read_header", "load_module", + "findImageInfo" }, + 25 }, +/*02*/ { { "excepman" } , + { "start", "reinit", "deinit", "getcommon", + "RegisterExceptionHandler", "RegisterPriorityExceptionHandler", + "RegisterDefaultExceptionHandler", "ReleaseExceptionHandler", + "ReleaseDefaultExceptionHandler" } , + 9 }, +/*03_4*/{ { "intrman" } , + { "start", "return_0", "deinit", "call3", + "RegisterIntrHandler", "ReleaseIntrHandler", "EnableIntr", "DisableIntr", + "CpuDisableIntr", "CpuEnableIntr", "syscall04", "syscall08", + "resetICTRL", "setICTRL", "syscall0C", "call15", + "call16", "CpuSuspendIntr", "CpuResumeIntr", "CpuSuspendIntr", + "CpuResumeIntr", "syscall10", "syscall14", "QueryIntrContext", + "QueryIntrStack", "iCatchMultiIntr", "retonly", "call27", + "set_h1", "reset_h1", "set_h2", "reset_h2" } , + 0x20 }, +/*05*/ { { "ssbusc" } , + { "start", "retonly", "return_0", "retonly", + "setTable1", "getTable1", "setTable2", "getTable2", + "setCOM_DELAY_1st", "getCOM_DELAY_1st", "setCOM_DELAY_2nd", "getCOM_DELAY_2nd", + "setCOM_DELAY_3rd", "getCOM_DELAY_3rd", "setCOM_DELAY_4th", "getCOM_DELAY_4th", + "setCOM_DELAY", "getCOM_DELAY" } , + 18 }, +/*06*/ { { "dmacman" } , + { "start", "retonly", "deinit", "retonly", + "SetD_MADR", "GetD_MADR", "SetD_BCR", "GetD_BCR", + "SetD_CHCR", "GetD_CHCR", "SetD_TADR", "GetD_TADR", + "Set_4_9_A", "Get_4_9_A", "SetDPCR", "GetDPCR", + "SetDPCR2", "GetDPCR2", "SetDPCR3", "GetDPCR3", + "SetDICR", "GetDICR", "SetDICR2", "GetDICR2", + "SetBF80157C", "GetBF80157C", "SetBF801578", "GetBF801578", + "SetDMA", "SetDMA_chainedSPU_SIF0", "SetDMA_SIF0", "SetDMA_SIF1", + "StartTransfer", "SetVal", "EnableDMAch", "DisableDMAch" } , + 36 }, +/*07_8*/{ { "timrman" } , + { "start", "retonly", "retonly", "call3", + "AllocHardTimer", "ReferHardTimer", "FreeHardTimer", "SetTimerMode", + "GetTimerStatus", "SetTimerCounter", "GetTimerCounter", "SetTimerCompare", + "GetTimerCompare", "SetHoldMode", "GetHoldMode", "GetHoldReg", + "GetHardTimerIntrCode" } , + 17 }, +/*09*/ { { "sysclib" } , + { "start", "reinit", "retonly", "retonly", + "setjmp", "longjmp", "toupper", "tolower", + "look_ctype_table", "get_ctype_table", "memchr", "memcmp", + "memcpy", "memmove", "memset", "bcmp", + "bcopy", "bzero", "prnt", "sprintf", + "strcat", "strchr", "strcmp", "strcpy", + "strcspn", "index", "rindex", "strlen", + "strncat", "strncmp", "strncpy", "strpbrk", + "strrchr", "strspn", "strstr", "strtok", + "strtol", "atob", "strtoul", "wmemcopy", + "wmemset", "vsprintf" } , + 0x2b }, +/*0A*/ { { "heaplib" } , + { "start", "retonly", "retonly", "retonly", + "CreateHeap", "DestroyHeap", "HeapMalloc", "HeapFree", + "HeapSize", "retonly", "retonly", "call11", + "call12", "call13", "call14", "call15", + "retonly", "retonly" } , + 18 }, +/*13*/ { { "stdio" } , + { "start", "unknown", "unknown", "unknown", + "printf" } , + 5 }, +/*14*/ { { "sifman" } , + { "start", "retonly", "deinit", "retonly", + "sceSif2Init", "sceSifInit", "sceSifSetDChain", "sceSifSetDma", + "sceSifDmaStat", "sceSifSend", "sceSifSendSync", "sceSifIsSending", + "sceSifSetSIF0DMA", "sceSifSendSync0", "sceSifIsSending0", "sceSifSetSIF1DMA", + "sceSifSendSync1", "sceSifIsSending1", "sceSifSetSIF2DMA", "sceSifSendSync2", + "sceSifIsSending2", "getEEIOPflags", "setEEIOPflags", "getIOPEEflags", + "setIOPEEflags", "getEErcvaddr", "getIOPrcvaddr", "setIOPrcvaddr", + "call28", "sceSifCheckInit", "setSif0CB", "resetSif0CB", + "retonly", "retonly", "retonly", "retonly" } , + 36 }, +/*16*/ { { "sifcmd" } , + { "start", "retonly", "deinit", "retonly", + "sceSifInitCmd", "sceSifExitCmd", "sceSifGetSreg", "sceSifSetSreg", + "sceSifSetCmdBuffer", "sceSifSetSysCmdBuffer", + "sceSifAddCmdHandler", "sceSifRemoveCmdHandler", + "sceSifSendCmd", "isceSifSendCmd", "sceSifInitRpc", "sceSifBindRpc", + "sceSifCallRpc", "sceSifRegisterRpc", + "sceSifCheckStatRpc", "sceSifSetRpcQueue", + "sceSifGetNextRequest", "sceSifExecRequest", + "sceSifRpcLoop", "sceSifGetOtherData", + "sceSifRemoveRpc", "sceSifRemoveRpcQueue", + "setSif1CB", "resetSif1CB", + "retonly", "retonly", "retonly", "retonly" } , + 32 }, +/*19*/ { { "cdvdman" } , + { "start", "retonly", "retonly", "retonly", + "sceCdInit", "sceCdStandby", "sceCdRead", "sceCdSeek", + "sceCdGetError", "sceCdGetToc", "sceCdSearchFile", "sceCdSync", + "sceCdGetDiskType", "sceCdDiskReady", "sceCdTrayReq", "sceCdStop", + "sceCdPosToInt", "sceCdIntToPos", "retonly", "call19", + "sceDvdRead", "sceCdCheckCmd", "_sceCdRI", "sceCdWriteILinkID", + "sceCdReadClock", "sceCdWriteRTC", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdStatus", "sceCdApplySCmd", "setHDmode", "sceCdOpenConfig", + "sceCdCloseConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdReadKey", + "sceCdDecSet", "sceCdCallback", "sceCdPause", "sceCdBreak", + "call40", "sceCdReadConsoleID", "sceCdWriteConsoleID", "sceCdGetMecaconVersion", + "sceCdGetReadPos", "AudioDigitalOut", "sceCdNop", "_sceGetFsvRbuf", + "_sceCdstm0Cb", "_sceCdstm1Cb", "_sceCdSC", "_sceCdRC", + "sceCdForbidDVDP", "sceCdReadSubQ", "sceCdApplyNCmd", "AutoAdjustCtrl", + "sceCdStInit", "sceCdStRead", "sceCdStSeek", "sceCdStStart", + "sceCdStStat", "sceCdStStop" } , + 62 }, +/*??*/ { { "sio2man" } , + { "start", "retonly", "deinit", "retonly", + "set8268_ctrl", "get8268_ctrl", "get826C_recv1", "call7_send1", + "call8_send1", "call9_send2", "call10_send2", "get8270_recv2", + "call12_set_params", "call13_get_params", "get8274_recv3", "set8278", + "get8278", "set827C", "get827C", "set8260_datain", + "get8264_dataout", "set8280_intr", "get8280_intr", "signalExchange1", + "signalExchange2", "packetExchange" } , + 26 } +}; + +#define Ra0 ((char*)PSXM(psxRegs.GPR.n.a0)) +#define Ra1 ((char*)PSXM(psxRegs.GPR.n.a1)) +#define Ra2 ((char*)PSXM(psxRegs.GPR.n.a2)) +#define Ra3 ((char*)PSXM(psxRegs.GPR.n.a3)) + +char* intrname[]={ +"INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00 +"INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04 +"INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08 +"INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C +"INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10 +"INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14 +"INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18 +"INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C +"INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20 +"INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24 +"INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28 +"INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C +"INT_30", "INT_31", "INT_32", "INT_33", //30 +"INT_34", "INT_35", "INT_36", "INT_37", //34 +"INT_38", "INT_39", "INT_3A", "INT_3B", //38 +"INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C +"INT_MAX" //40 +}; + +void zeroEx() { + u32 pc; + u32 code; + char *lib; + char *fname = NULL; + int i; + + if (!Config.PsxOut) return; + + pc = psxRegs.pc; + while (PSXMu32(pc) != 0x41e00000) pc-=4; + + lib = (char*)PSXM(pc+12); + code = PSXMu32(psxRegs.pc - 4) & 0xffff; + + for (i=0; i= (u32)irxlibs[i].maxn) break; + + fname = irxlibs[i].names[code]; break; + } + } + +#ifdef PSXBIOS_LOG + {char libz[9]; memcpy(libz, lib, 8); libz[8]=0; + PSXBIOS_LOG("%s: %s (%x)" + " (%x, %x, %x, %x)" //comment this line to disable param showing + , libz, fname == NULL ? "unknown" : fname, code, + psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + } +#endif + +// Log=0; +// if (!strcmp(lib, "intrman") && code == 0x11) Log=1; +// if (!strcmp(lib, "sifman") && code == 0x5) Log=1; +// if (!strcmp(lib, "sifcmd") && code == 0x4) Log=1; +// if (!strcmp(lib, "thbase") && code == 0x6) Log=1; +/* + if (!strcmp(lib, "sifcmd") && code == 0xe) { + branchPC = psxRegs.GPR.n.ra; + psxRegs.GPR.n.v0 = 0; + return; + } +*/ + if (!strncmp(lib, "ioman", 5) && code == 7) { + if (psxRegs.GPR.n.a0 == 1) { + pc = psxRegs.pc; + bios_write(); + psxRegs.pc = pc; + } + } + + if (!strncmp(lib, "sysmem", 6) && code == 0xe) { + bios_printf(); + psxRegs.pc = psxRegs.GPR.n.ra; + } + + if (!strncmp(lib, "loadcore", 8) && code == 6) { + SysPrintf("loadcore RegisterLibraryEntries (%x): %8.8s\n", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12)); + } + + if (!strncmp(lib, "intrman", 7) && code == 4) { + SysPrintf("intrman RegisterIntrHandler (%x): intr %s, handler %x\n", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2); + } + + if (!strncmp(lib, "sifcmd", 6) && code == 17) { + SysPrintf("sifcmd sceSifRegisterRpc (%x): rpc_id %x\n", psxRegs.pc, psxRegs.GPR.n.a1); + } + +#ifdef PSXBIOS_LOG + if (!strncmp(lib, "sysclib", 8)) { + switch (code) { + case 0x16: // strcmp + if (varLog & 0x00800000) EMU_LOG(" \"%s\": \"%s\"", Ra0, Ra1); + break; + + case 0x1e: // strncpy + if (varLog & 0x00800000) EMU_LOG(" \"%s\"", Ra1); + break; + } + } +#endif + +#ifdef PSXBIOS_LOG + if (varLog & 0x00800000) EMU_LOG("\n"); +#endif + +/* psxRegs.pc = branchPC; + pc = psxRegs.GPR.n.ra; + while (psxRegs.pc != pc) psxCpu->ExecuteBlock(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("%s: %s (%x) END\n", lib, fname == NULL ? "unknown" : fname, code); +#endif*/ +} +/*/==========================================CALL LOG +char* getName(char *file, u32 addr){ + FILE *f; u32 a; + static char name[100]; + + f=fopen(file, "r"); + if (!f) + name[0]=0; + else{ + while (!feof(f)){ + fscanf(f, "%08X %s\r\n", &a, name); + if (a==addr)break; + } + fclose(f); + } + return name; +} + +void spyFunctions(){ + register irxImageInfo *iii; + if (psxRegs.pc >= 0x200000) return; + for (iii=(irxImageInfo*)PSXM(0x800); iii && iii->text_size; + iii=iii->next ? (irxImageInfo*)PSXM(iii->next) : NULL) + if (iii->vaddr<=psxRegs.pc && psxRegs.pcvaddr+iii->text_size+iii->data_size+iii->bss_size){ + if (strcmp("secrman_for_cex", PSXM(iii->name))==0){ + char *name=getName("secrman.fun", psxRegs.pc-iii->vaddr); + if (strncmp("__push_params", name, 13)==0){ + PAD_LOG(PSXM(psxRegs.GPR.n.a0), psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + }else{ + PAD_LOG("secrman: %s (ra=%06X cycle=%d)\n", name, psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}}else + if (strcmp("mcman", PSXM(iii->name))==0){ + PAD_LOG("mcman: %s (ra=%06X cycle=%d)\n", getName("mcman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("padman", PSXM(iii->name))==0){ + PAD_LOG("padman: %s (ra=%06X cycle=%d)\n", getName("padman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("sio2man", PSXM(iii->name))==0){ + PAD_LOG("sio2man: %s (ra=%06X cycle=%d)\n", getName("sio2man.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);} + break; + } +} +*/ +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow) +void psxADDIU() { if (!_Rt_) { zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im +void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im +void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im +void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im +void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed) +void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < _ImmU_; } // Rt = Rs < Im (Unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow) +void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt +void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow) +void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt +void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt +void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt +void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt +void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt +void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed) +void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void psxDIV() { + if (_rRt_ != 0) { + _rLo_ = _i32(_rRs_) / _i32(_rRt_); + _rHi_ = _i32(_rRs_) % _i32(_rRt_); + } +} + +void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } +} + +void psxMULT() { + u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +void psxMULTU() { + u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); +#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } + +void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa +void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic) +void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs +void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) +void psxSRLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi +void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs +void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +void psxBREAK() { + // Break exception - psx rom doens't handles this + psxRegs.pc -= 4; + psxException(0x24, branch); +} + +void psxSYSCALL() { + psxRegs.pc -= 4; + psxException(0x20, branch); + +} + +void psxRFE() { +// SysPrintf("RFE\n"); + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +// Log=0; +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_); + +void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +void psxJ() { doBranch(_JumpTarget_); } +void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); /*spyFunctions();*/ } + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void psxJR() { doBranch(_u32(_rRs_)); } +void psxJALR() { if (_Rd_) { _SetLink(_Rd_); } doBranch(_u32(_rRs_)); } + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +#define _oB_ (_u32(_rRs_) + _Imm_) + +void psxLB() { + if (_Rt_) { + _rRt_ = (s8 )psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLBU() { + if (_Rt_) { + _rRt_ = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLH() { + if (_Rt_) { + _rRt_ = (s16)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLHU() { + if (_Rt_) { + _rRt_ = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLW() { + if (_Rt_) { + _rRt_ = psxMemRead32(_oB_); + } else { + psxMemRead32(_oB_); + } +} + +void psxLWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0x00ffffff >> shift) ) | + ( mem << (24 - shift) ); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + + */ +} + +void psxLWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0xffffff00 << (24 - shift)) ) | + ( mem >> shift ); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + + */ +} + +void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); } +void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); } +void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); } + +void psxSWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) >> (24 - shift) ) ) | + ( mem & (0xffffff00 << shift) )); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + + */ +} + +void psxSWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) << shift ) | + (mem & (0x00ffffff >> (24 - shift)) ) ) ); + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + + */ +} + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } +void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } + +void psxMTC0() { _rFs_ = _u32(_rRt_); } +void psxCTC0() { _rFs_ = _u32(_rRt_); } + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +void psxNULL() { +SysPrintf("psx: Unimplemented op %x\n", psxRegs.code); +} + +void psxSPECIAL() { + psxSPC[_Funct_](); +} + +void psxREGIMM() { + psxREG[_Rt_](); +} + +void psxCOP0() { + psxCP0[_Rs_](); +} + +void psxCOP2() { + psxCP2[_Funct_](); +} + +void psxBASIC() { + psxCP2BSC[_Rs_](); +} + + +void (*psxBSC[64])() = { + psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ, + psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI , + psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, + psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL +}; + + +void (*psxSPC[64])() = { + psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV, + psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL, + psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL, + psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL, + psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR , + psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL +}; + +void (*psxREG[32])() = { + psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP0[32])() = { + psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP2[64])() = { + psxBASIC, psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL, psxNULL, // 00 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 08 + psxNULL , psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 10 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 18 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, // 28 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL // 38 +}; + +void (*psxCP2BSC[32])() = { + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + + +/////////////////////////////////////////// + +static int intInit() { + return 0; +} + +static void intReset() { +} + +static void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + while (EEsCycle > 0){ + branch2 = 0; + while (!branch2) + execI(); + } +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +}; diff --git a/PsxMem.c b/PsxMem.c new file mode 100644 index 0000000000..9cae17ebee --- /dev/null +++ b/PsxMem.c @@ -0,0 +1,1605 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" +#include "VU.h" +#include "iCore.h" +#include "ir3000A.h" + +extern u32 g_psxMaxRecMem; +int g_psxWriteOk=1; +static u32 writectrl; + +#ifdef WIN32_VIRTUAL_MEM + +int psxMemInit() +{ + // all mem taken care by memInit + return 0; +} + +void psxMemReset() +{ + memset(psxM, 0, 0x00200000); +} + +void psxMemShutdown() +{ +} + +#ifdef _DEBUG + +#define ASSERT_WRITEOK \ +{ \ + __asm cmp g_psxWriteOk, 1 \ + __asm je WriteOk \ + __asm int 10 \ +} \ +WriteOk: \ + +#else +#define ASSERT_WRITEOK +#endif + +u8 psxMemRead8(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + break; + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + mem &= 0x1fffffff; + return psxHw4Read8(mem); + + case 0x1000: return DEV9read8(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u8*)PSXM(mem); + } +} + +__declspec(naked) void psxRecMemRead8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f40 + je hw4read + cmp dx, 0x1000 + je devread + cmp dx, 0x1f00 + je spuread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead8 + add esp, 4 + ret + +hw4read: + push ecx + call psxHw4Read8 + add esp, 4 + ret + +devread: + push ecx + call DEV9read8 + // stack already incremented + ret + +spuread: + push ecx + call SPU2read + // stack already incremented + ret + } +} + +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + return psxHwConstRead8(x86reg, mem&0x1fffffff, sign); + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + return psxHw4ConstRead8(x86reg, mem&0x1fffffff, sign); + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(x86reg, EAX); + else MOVZX32R8toR(x86reg, EAX); + return 0; + + default: + _eeReadConstMem8(x86reg, (u32)PSXM(mem), sign); + return 0; + } +} + +u16 psxMemRead16(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu16(0x1000F240) | 0x0002; + case 0x60: return 0; + default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1f90: + return SPU2read(mem & 0x1FFFFFFF); + case 0x1000: + return DEV9read16(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u16*)PSXM(mem); + } +} + +__declspec(naked) void psxRecMemRead16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f90 + je spuread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead16 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 2 + jmp End +Sif60: + xor eax, eax + jmp End + +spuread: + push ecx + call SPU2read + // stack already incremented + +End: + ret + +devread: + push ecx + call DEV9read16 + // stack already incremented + ret + } +} + +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead16(x86reg, mem&0x1fffffff, sign); + + case 0x1d00: + + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xF240, sign); + OR32ItoR(x86reg, 0x0002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0), sign); + break; + } + return 0; + + case 0x1f90: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + default: + assert( g_psxWriteOk ); + _eeReadConstMem16(x86reg, (u32)PSXM(mem), sign); + return 0; + } + + return 0; +} + +u32 psxMemRead32(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu32(0x1000F240) | 0xF0000002; + case 0x60: return 0; + default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1fff: return g_psxWriteOk; + case 0x1000: + return DEV9read32(mem & 0x1FFFFFFF); + + default: + assert(g_psxWriteOk); + if( mem == 0xfffe0130 ) + return writectrl; + else if( mem == 0xffffffff ) + return writectrl; + else if( g_psxWriteOk ) + return *(u32*)PSXM(mem); + else return 0; + } +} + +__declspec(naked) void psxRecMemRead32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + cmp ecx, 0x1ffe0130 + je WriteCtrlRead + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead32 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + // do the read from ps2 mem + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 0xf0000002 + jmp End +Sif60: + xor eax, eax +End: + ret + +devread: + push ecx + call DEV9read32 + // stack already incremented + ret + +WriteCtrlRead: + mov eax, writectrl + ret + } +} + +int psxRecMemConstRead32(u32 x86reg, u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead32(x86reg, mem&0x1fffffff); + + case 0x1d00: + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xF240); + OR32ItoR(x86reg, 0xf0000002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0)); + break; + } + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read32); + return 1; + + default: + if( mem == 0xfffe0130 ) + MOV32MtoR(x86reg, (u32)&writectrl); + else { + XOR32RtoR(x86reg, x86reg); + CMP32ItoM((u32)&g_psxWriteOk, 0); + CMOVNE32MtoR(x86reg, (u32)PSXM(mem)); + } + + return 0; + } +} + +void psxMemWrite8(u32 mem, u8 value) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + break; + + case 0x1f40: + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + break; + + case 0x1d00: + SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + *(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value; + break; + + case 0x1000: + DEV9write8(mem & 0x1fffffff, value); + return; + + default: + assert(g_psxWriteOk); + *(u8 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +__declspec(naked) void psxRecMemWrite8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f40 + je hw4write + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov byte ptr [ecx+PS2MEM_BASE_], al + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite8 + add esp, 8 + ret + +hw4write: + push eax + push ecx + call psxHw4Write8 + add esp, 8 + ret + +devwrite: + push eax + push ecx + call DEV9write8 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite8(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + psxHwConstWrite8(mem&0x1fffffff, mmreg); + return 0; + case 0x1f40: + psxHw4ConstWrite8(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + assert(0); + _eeWriteConstMem8((u32)(PS2MEM_HW+0xf200+(mem&0xff)), mmreg); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write8); + return 0; + + default: + _eeWriteConstMem8((u32)PSXM(mem), mmreg); + return 1; + } +} + +void psxMemWrite16(u32 mem, u16 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + default: + assert(0); + } + return; + + case 0x1f90: + SPU2write(mem & 0x1FFFFFFF, value); return; + + case 0x1000: + DEV9write16(mem & 0x1fffffff, value); return; + default: + assert( g_psxWriteOk ); + *(u16 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +__declspec(naked) void psxRecMemWrite16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f90 + je spuwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov word ptr [ecx+PS2MEM_BASE_], ax + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite16 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], ax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif60: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +spuwrite: + push eax + push ecx + call SPU2write + // stack alwritey incremented + ret + +devwrite: + push eax + push ecx + call DEV9write16 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite16(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite16(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem16((u32)(PS2MEM_HW+0xf210), mmreg); + return 0; + case 0x40: + { + // delete x86reg + _eeMoveMMREGtoR(EAX, mmreg); + + assert( mmreg != EBX ); + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1f90: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)SPU2write); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write16); + return 0; + + default: + _eeWriteConstMem16((u32)PSXM(mem), mmreg); + return 1; + } +} + +void psxMemWrite32(u32 mem, u32 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + default: + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + } + + return; + + case 0x1000: + DEV9write32(mem & 0x1fffffff, value); + return; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + g_psxWriteOk = 0; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + g_psxWriteOk = 1; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + break; + + default: + + if( g_psxWriteOk ) { + *(u32 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + } + + break; + } +} + +__declspec(naked) void psxRecMemWrite32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + cmp dx, 0x1ffe + je WriteCtrl + } + + __asm { + // rom writes, has to be PS2MEM_BASE_ + test g_psxWriteOk, 1 + jz endwrite + +memwrite: + mov dword ptr [ecx+PS2MEM_BASE_], eax +endwrite: + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + cmp dl, 0x30 + je Sif30 + cmp dl, 0x20 + je Sif20 + + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], ax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif30: + or dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif20: + not eax + and dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif60: + mov dword ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +devwrite: + push eax + push ecx + call DEV9write32 + // stack alwritey incremented + ret + +WriteCtrl: + cmp ecx, 0x1ffe0130 + jne End + + mov writectrl, eax + + cmp eax, 0x800 + je SetWriteNotOk + cmp eax, 0x804 + je SetWriteNotOk + cmp eax, 0xc00 + je SetWriteNotOk + cmp eax, 0xc04 + je SetWriteNotOk + cmp eax, 0xcc0 + je SetWriteNotOk + cmp eax, 0xcc4 + je SetWriteNotOk + cmp eax, 0x0c4 + je SetWriteNotOk + + // test ok + cmp eax, 0x1e988 + je SetWriteOk + cmp eax, 0x1edd8 + je SetWriteOk + +End: + ret + +SetWriteNotOk: + mov g_psxWriteOk, 0 + ret +SetWriteOk: + mov g_psxWriteOk, 1 + ret + } +} + +int psxRecMemConstWrite32(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite32(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem32((u32)PS2MEM_HW+0xf210, mmreg); + return 0; + case 0x20: + // write to ps2 mem + // delete x86reg + if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM((u32)PS2MEM_HW+0xf220, ~g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else { + NOT32R(mmreg); + AND32RtoM((u32)PS2MEM_HW+0xf220, mmreg); + } + return 0; + case 0x30: + // write to ps2 mem + _eeWriteConstMem32OP((u32)PS2MEM_HW+0xf230, mmreg, 1); + return 0; + case 0x40: + { + // delete x86reg + assert( mmreg != EBX ); + + _eeMoveMMREGtoR(EAX, mmreg); + + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + u8* ptrs[9]; + + _eeWriteConstMem32((u32)&writectrl, mmreg); + + if( IS_PSXCONSTREG(mmreg) ) { + switch (g_psxConstRegs[(mmreg>>16)&0x1f]) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + MOV32ItoM((u32)&g_psxWriteOk, 0); + break; + case 0x1e988: + case 0x1edd8: + MOV32ItoM((u32)&g_psxWriteOk, 1); + break; + default: + assert(0); + } + } + else { + // not ok + CMP32ItoR(mmreg, 0x800); + ptrs[0] = JE8(0); + CMP32ItoR(mmreg, 0x804); + ptrs[1] = JE8(0); + CMP32ItoR(mmreg, 0xc00); + ptrs[2] = JE8(0); + CMP32ItoR(mmreg, 0xc04); + ptrs[3] = JE8(0); + CMP32ItoR(mmreg, 0xcc0); + ptrs[4] = JE8(0); + CMP32ItoR(mmreg, 0xcc4); + ptrs[5] = JE8(0); + CMP32ItoR(mmreg, 0x0c4); + ptrs[6] = JE8(0); + + // ok + CMP32ItoR(mmreg, 0x1e988); + ptrs[7] = JE8(0); + CMP32ItoR(mmreg, 0x1edd8); + ptrs[8] = JE8(0); + + x86SetJ8(ptrs[0]); + x86SetJ8(ptrs[1]); + x86SetJ8(ptrs[2]); + x86SetJ8(ptrs[3]); + x86SetJ8(ptrs[4]); + x86SetJ8(ptrs[5]); + x86SetJ8(ptrs[6]); + MOV32ItoM((u32)&g_psxWriteOk, 0); + ptrs[0] = JMP8(0); + + x86SetJ8(ptrs[7]); + x86SetJ8(ptrs[8]); + MOV32ItoM((u32)&g_psxWriteOk, 1); + + x86SetJ8(ptrs[0]); + } + } + return 0; + + default: + TEST8ItoM((u32)&g_psxWriteOk, 1); + j8Ptr[0] = JZ8(0); + _eeWriteConstMem32((u32)PSXM(mem), mmreg); + x86SetJ8(j8Ptr[0]); + return 1; + } +} + +#else + +// TLB functions + +s8 *psxM; +s8 *psxP; +s8 *psxH; +s8 *psxS; +uptr *psxMemWLUT; +uptr *psxMemRLUT; + +int psxMemInit() +{ + int i; + + psxMemRLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + memset(psxMemRLUT, 0, 0x10000 * sizeof(uptr)); + memset(psxMemWLUT, 0, 0x10000 * sizeof(uptr)); + + psxM = (char*)_aligned_malloc(0x00200000,16); + psxP = (char*)_aligned_malloc(0x00010000,16); + psxH = (char*)_aligned_malloc(0x00010000,16); + psxS = (char*)_aligned_malloc(0x00010000,16); + if (psxMemRLUT == NULL || psxMemWLUT == NULL || + psxM == NULL || psxP == NULL || psxH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + memset(psxH, 0, 0x00010000); + memset(psxS, 0, 0x00010000); + + +// MemR + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x9fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0xbfc0] = (uptr)&PS2MEM_ROM[i << 16]; + + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x9e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0xbe00] = (uptr)&PS2MEM_ROM1[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + +// MemW + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + +// for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16]; + +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + + return 0; +} + +void psxMemReset() { + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + //memset(psxS, 0, 0x00010000); +} + +void psxMemShutdown() +{ + _aligned_free(psxM); + _aligned_free(psxP); + _aligned_free(psxH); + _aligned_free(psxMemRLUT); + _aligned_free(psxMemWLUT); +} + +u8 psxMemRead8(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + return psxHw4Read8(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + return *(u8 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lb %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u16 psxMemRead16(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u16 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu16(0x1000F200); + break; + case 0x10: + ret= psHu16(0x1000F210); + break; + case 0x40: + ret= psHu16(0x1000F240) | 0x0002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu16(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u16 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1F90) + return SPU2read(mem & 0x1FFFFFFF); + if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lh %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u32 psxMemRead32(u32 mem) { + char *p; + u32 t; + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + } else { + //see also Hw.c + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u32 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu32(0x1000F200); + break; + case 0x10: + ret= psHu32(0x1000F210); + break; + case 0x20: + ret= psHu32(0x1000F220); + break; + case 0x30: // EE Side + ret= psHu32(0x1000F230); + break; + case 0x40: + ret= psHu32(0x1000F240) | 0xF0000002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu32(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u32 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF); + + if (mem != 0xfffe0130) { +#ifdef PSXMEM_LOG + if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem); +#endif + } else { + return writectrl; + } + return 0; + } + } +} + +void psxMemWrite8(u32 mem, u8 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u8 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + if (t == 0x1d00) { + psxSu8(mem) = value; return; + } + if (t == 0x1000) { + DEV9write8(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite16(u32 mem, u16 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); + *(u16 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (t == 0x1d00) { + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu16(mem) = value; return; + } + if (t == 0x1F90) { + SPU2write(mem & 0x1FFFFFFF, value); return; + } + if (t == 0x1000) { + DEV9write16(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite32(u32 mem, u32 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + } else { + //see also Hw.c + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u32 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (mem != 0xfffe0130) { + if (t == 0x1d00) { +#ifdef MEM_LOG + MEM_LOG("iop Sif reg write %x value %x\n", mem, value); +#endif + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu32(mem) = value; + + // write to ps2 mem + if( (mem & 0xf0) != 0x60 ) + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + return; + } + if (t == 0x1000) { + DEV9write32(mem & 0x1fffffff, value); return; + } + + //if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1); +#ifdef PSXMEM_LOG + if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); } +#endif + } else { + int i; + + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + if (g_psxWriteOk == 0) break; + g_psxWriteOk = 0; + memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(uptr)); +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + if (g_psxWriteOk == 1) break; + g_psxWriteOk = 1; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + } + } +} + +#endif \ No newline at end of file diff --git a/PsxMem.h b/PsxMem.h new file mode 100644 index 0000000000..b9d861b03a --- /dev/null +++ b/PsxMem.h @@ -0,0 +1,113 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXMEMORY_H__ +#define __PSXMEMORY_H__ + +#ifdef WIN32_VIRTUAL_MEM + +// VM +#define psxM PS2MEM_PSX +#define psxH PS2MEM_PSXHW + +#define PSXM(mem) ((mem&0x10000000)?PSM(mem):(PS2MEM_PSX+(mem&0x1fffff))) +#define _PSXM(mem) PSXM(mem) + +#else + +// TLB +extern s8 *psxM; +extern s8 *psxP; +extern s8 *psxH; +extern s8 *psxS; +extern uptr *psxMemWLUT; +extern uptr *psxMemRLUT; + +#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) +#define _PSXM(mem) ((void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) + +#define psxSs8(mem) psxS[(mem) & 0xffff] +#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff]) +#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff]) +#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff]) +#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff]) +#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff]) + +#endif + +#define psxMs8(mem) psxM[(mem) & 0x1fffff] +#define psxMs16(mem) (*(s16*)&psxM[(mem) & 0x1fffff]) +#define psxMs32(mem) (*(s32*)&psxM[(mem) & 0x1fffff]) +#define psxMu8(mem) (*(u8*) &psxM[(mem) & 0x1fffff]) +#define psxMu16(mem) (*(u16*)&psxM[(mem) & 0x1fffff]) +#define psxMu32(mem) (*(u32*)&psxM[(mem) & 0x1fffff]) +#define psxMu64(mem) (*(u64*)&psxM[(mem) & 0x1fffff]) + +#define psxPs8(mem) psxP[(mem) & 0xffff] +#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff]) +#define psxPs32(mem) (*(s32*)&psxP[(mem) & 0xffff]) +#define psxPu8(mem) (*(u8*) &psxP[(mem) & 0xffff]) +#define psxPu16(mem) (*(u16*)&psxP[(mem) & 0xffff]) +#define psxPu32(mem) (*(u32*)&psxP[(mem) & 0xffff]) + +#define psxHs8(mem) psxH[(mem) & 0xffff] +#define psxHs16(mem) (*(s16*)&psxH[(mem) & 0xffff]) +#define psxHs32(mem) (*(s32*)&psxH[(mem) & 0xffff]) +#define psxHu8(mem) (*(u8*) &psxH[(mem) & 0xffff]) +#define psxHu16(mem) (*(u16*)&psxH[(mem) & 0xffff]) +#define psxHu32(mem) (*(u32*)&psxH[(mem) & 0xffff]) + +#define PSXMs8(mem) (*(s8 *)_PSXM(mem)) +#define PSXMs16(mem) (*(s16*)_PSXM(mem)) +#define PSXMs32(mem) (*(s32*)_PSXM(mem)) +#define PSXMu8(mem) (*(u8 *)_PSXM(mem)) +#define PSXMu16(mem) (*(u16*)_PSXM(mem)) +#define PSXMu32(mem) (*(u32*)_PSXM(mem)) + +int psxMemInit(); +void psxMemReset(); +void psxMemShutdown(); + +u8 psxMemRead8 (u32 mem); +u16 psxMemRead16(u32 mem); +u32 psxMemRead32(u32 mem); +void psxMemWrite8 (u32 mem, u8 value); +void psxMemWrite16(u32 mem, u16 value); +void psxMemWrite32(u32 mem, u32 value); + +// x86reg and mmreg are always x86 regs +void psxRecMemRead8(); +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead16(); +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead32(); +int psxRecMemConstRead32(u32 x86reg, u32 mem); + +void psxRecMemWrite8(); +int psxRecMemConstWrite8(u32 mem, int mmreg); + +void psxRecMemWrite16(); +int psxRecMemConstWrite16(u32 mem, int mmreg); + +void psxRecMemWrite32(); +int psxRecMemConstWrite32(u32 mem, int mmreg); + + +#endif /* __PSXMEMORY_H__ */ diff --git a/PsxSio2.c b/PsxSio2.c new file mode 100644 index 0000000000..6f83c10f45 --- /dev/null +++ b/PsxSio2.c @@ -0,0 +1,249 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + +/* +w [8268]=0x3bc sio2_start/sio2man +r [8270] padman_start/padman + padman->7480[00]=bit4; + padman->7480[13]=bit5; + packetExchange(&703F8); +w [8268]|=0x0C; +........ +w [8268]|=0x01; + +only recv2 & dataout influences padman +*/ + +// 0xBF808200,0xBF808204,0xBF808208,0xBF80820C, +// 0xBF808210,0xBF808214,0xBF808218,0xBF80821C, packet->sendArray3 +// 0xBF808220,0xBF808224,0xBF808228,0xBF80822C, call12/13_s/getparams +// 0xBF808230,0xBF808234,0xBF808238,0xBF80823C, + +// 0xBF808240,0xBF808248,0xBF808250,0xBF808258, packet->sendArray1/call_7/8 +// 0xBF808244,0xBF80824C,0xBF808254,0xBF80825C, packet->sendArray2/call_9/10 + +// 0xBF808260, serial data/fifo in/out s/get8260_datain/out packet->sendbuf(nomem!) +// 0xBF808268, ctrl s/get8268_ctrl + +// 0xBF80826C, packet->recv1/2/3 get826C_recv1, get8270_recv2, get8274_recv3 +// 0xBF808270,0xBF808274, + +// 0xBF808278,0xBF80827C, s/get8278, s/get827C +// 0xBF808280 interrupt related s/get8280_intr + + +void sio2Reset() { + SysPrintf("Sio2 init\n"); + memset(&sio2, 0, sizeof(sio2)); + sio2.packet.recvVal1 = 0x1D100; // Nothing is connected at start +} + +u32 sio2_getRecv1() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv1 = %x\n",sio2.packet.recvVal1); +#endif + return sio2.packet.recvVal1; +} + +u32 sio2_getRecv2() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv2 = %x\n",0xF); +#endif + return 0xF; +}//0, 0x10, 0x20, 0x10 | 0x20; bits 4 & 5 + +u32 sio2_getRecv3() { + if(sio2.packet.recvVal3 == 0x8C || sio2.packet.recvVal3 == 0x8b || + sio2.packet.recvVal3 == 0x83) + { +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio2.packet.recvVal3); +#endif + sio.packetsize = sio2.packet.recvVal3; + sio2.packet.recvVal3 = 0; // Reset + return sio.packetsize; + }else{ +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio.packetsize << 16); +#endif + return sio.packetsize << 16; + } +} + +void sio2_setSend1(u32 index, u32 value){sio2.packet.sendArray1[index]=value;} //0->3 +u32 sio2_getSend1(u32 index){return sio2.packet.sendArray1[index];} //0->3 +void sio2_setSend2(u32 index, u32 value){sio2.packet.sendArray2[index]=value;} //0->3 +u32 sio2_getSend2(u32 index){return sio2.packet.sendArray2[index];} //0->3 +void sio2_setSend3(u32 index, u32 value) {int i; +/* if (index == 0) { + printf("value: %x\n", value); + }*/ + sio2.packet.sendArray3[index]=value; +#ifdef PAD_LOG + if (index==15){ + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray1[i]);}PAD_LOG("\n"); + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray2[i]);}PAD_LOG("\n"); + for (i=0; i<8; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + for ( ; i<16; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + } +#endif +} //0->15 + +u32 sio2_getSend3(u32 index) {return sio2.packet.sendArray3[index];} //0->15 + +void sio2_setCtrl(u32 value){ + sio2.ctrl=value; + if (sio2.ctrl & 1){ //recv packet + //handle data that had been sent + + //trigger interupt for SIO2 + psxHu32(0x1070)|=0x20000; + sio2.recvIndex=0; + sio2.ctrl &= ~1; + } else { // send packet + //clean up + sio2.packet.sendSize=0; //reset size + sio2.cmdport=0; + sio2.cmdlength=0; + sioWriteCtrl16(SIO_RESET); + } +} +u32 sio2_getCtrl(){return sio2.ctrl;} + +void sio2_setIntr(u32 value){sio2.intr=value;} +u32 sio2_getIntr(){ + return sio2.intr; +} + +void sio2_set8278(u32 value){sio2._8278=value;} +u32 sio2_get8278(){return sio2._8278;} +void sio2_set827C(u32 value){sio2._827C=value;} +u32 sio2_get827C(){return sio2._827C;} + +void sio2_fifoIn(u8 value){ + u16 ctrl=0x0002; + if (sio2.packet.sendArray3[sio2.cmdport] && (sio2.cmdlength==0)){//else do nothing! + + sio2.cmdlength=(sio2.packet.sendArray3[sio2.cmdport] >> 8) & 0x1FF; + ctrl &= ~0x2000; + ctrl |= (sio2.packet.sendArray3[sio2.cmdport] & 1) << 13;//it is correct this way:P; what did you want to do? + //sioWriteCtrl16(SIO_RESET); + sioWriteCtrl16(ctrl); +#ifdef PSXDMA_LOG + PSXDMA_LOG("sio2_fifoIn: ctrl = %x, cmdlength = %x, cmdport = %d (%x)\n", ctrl, sio2.cmdlength, sio2.cmdport, sio2.packet.sendArray3[sio2.cmdport]); +#endif + sio2.cmdport++;//position in sendArray3 + } + if (sio2.cmdlength) sio2.cmdlength--; + +// sioWriteCtrl16(ctrl); + + sioWrite8(value); + if (sio2.packet.sendSize > BUFSIZE) {//asadr + SysPrintf("*PCSX2*: sendSize >= %d\n", BUFSIZE); + } else { + sio2.buf[sio2.packet.sendSize] = sioRead8(); + sio2.packet.sendSize++; + } +} + +u8 sio2_fifoOut(){ + u8 value=0; + + if (sio2.recvIndex <= sio2.packet.sendSize){ + value = sio2.buf[sio2.recvIndex++]; + } else { + SysPrintf("*PCSX2*: buffer overrun\n"); + } + return value; //no data +} + +///////////////////////////////////////////////// +//////////////////////////////////////////// DMA +///////////////////////////////////////////////// + +void psxDma11(u32 madr, u32 bcr, u32 chcr) { + int wordsize, totalblocks; +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 11 - SIO2 in *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x01000201) return; + wordsize = (bcr & 0xffff); + totalblocks = (bcr >> 16); + bcr = (totalblocks * wordsize) * 4; // 8 bits + PSX_INT(11,(bcr>>2)); + while (bcr > 0) { + sio2_fifoIn(PSXMu8(madr)); + bcr--; madr++; + if(sio2.packet.sendSize == BUFSIZE) break; + } + HW_DMA11_MADR = madr; + HW_DMA11_BCR = bcr; + +} + +int psxDMA11Interrupt() +{ + HW_DMA11_CHCR &= ~0x01000000; + psxDmaInterrupt2(4); + return 1; +} + +void psxDma12(u32 madr, u32 bcr, u32 chcr) { + int wordsize, totalblocks; +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 12 - SIO2 out *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x41000200) return; + + wordsize = (bcr & 0xffff); + totalblocks = (bcr >> 16); + bcr = (totalblocks * wordsize) * 4; // 8 bits + sio2.recvIndex = 0; // Set To start asadr + PSX_INT(12,(bcr>>2)); + while (bcr > 0) { + PSXMu8(madr) = sio2_fifoOut(); + bcr--; madr++; + if(sio2.recvIndex == sio2.packet.sendSize) break; + } + HW_DMA12_MADR = madr; + HW_DMA12_BCR = bcr; + PSX_INT(12,(bcr>>2)); + +} + +int psxDMA12Interrupt() +{ + HW_DMA12_CHCR &= ~0x01000000; + psxDmaInterrupt2(5); + return 1; +} + +int sio2Freeze(gzFile f, int Mode) { + gzfreeze(&sio2, sizeof(sio2)); + + return 0; +} + diff --git a/PsxSio2.h b/PsxSio2.h new file mode 100644 index 0000000000..6f5aea8034 --- /dev/null +++ b/PsxSio2.h @@ -0,0 +1,98 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXSIO2_H__ +#define __PSXSIO2_H__ + + +#define BUFSIZE 1024 + +//from sio2man.c + +struct SIO2_packet { + unsigned int recvVal1; // 0x00 + unsigned int sendArray1[4]; // 0x04-0x10 + unsigned int sendArray2[4]; // 0x14-0x20 + + unsigned int recvVal2; // 0x24 + + unsigned int sendArray3[16]; // 0x28-0x64 + + unsigned int recvVal3; // 0x68 + + int sendSize; // 0x6C + int recvSize; // 0x70 + + unsigned char *sendBuf; // 0x74 + unsigned char *recvBuf; // 0x78 + + unsigned int dmacAddress1; + unsigned int dmacSize1; + unsigned int dmacCount1; + unsigned int dmacAddress2; + unsigned int dmacSize2; + unsigned int dmacCount2; +}; + +typedef struct { + struct SIO2_packet packet; + u32 ctrl; + u32 intr; + u32 _8278, _827C; + int recvIndex; + u32 hackedRecv; + int cmdport; + int cmdlength; //length of a command sent to a port + //is less_equal than the dma send size + u8 buf[BUFSIZE]; +} sio2Struct; + +sio2Struct sio2; + +void sio2Reset(); +u32 sio2_getRecv1(); +u32 sio2_getRecv2(); +u32 sio2_getRecv3(); +void sio2_setSend1(u32 index, u32 value); //0->3 +u32 sio2_getSend1(u32 index); //0->3 +void sio2_setSend2(u32 index, u32 value); //0->3 +u32 sio2_getSend2(u32 index); //0->3 +void sio2_setSend3(u32 index, u32 value); //0->15 +u32 sio2_getSend3(u32 index); //0->15 + +void sio2_setCtrl(u32 value); +u32 sio2_getCtrl(); +void sio2_setIntr(u32 value); +u32 sio2_getIntr(); +void sio2_set8278(u32 value); +u32 sio2_get8278(); +void sio2_set827C(u32 value); +u32 sio2_get827C(); + +void sio2_fifoIn(u8 value); +u8 sio2_fifoOut(); + +void psxDma11(u32 madr, u32 bcr, u32 chcr); +void psxDma12(u32 madr, u32 bcr, u32 chcr); + +int psxDMA11Interrupt(); +int psxDMA12Interrupt(); +int sio2Freeze(gzFile f, int Mode); + +#endif /* __PSXSIO2_H__ */ + diff --git a/R3000A.c b/R3000A.c new file mode 100644 index 0000000000..7e9d442a6a --- /dev/null +++ b/R3000A.c @@ -0,0 +1,214 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" + +// used for constant propagation +R3000Acpu *psxCpu; +u32 g_psxConstRegs[32]; +u32 g_psxHasConstReg, g_psxFlushedConstReg; + +__declspec(align(16)) psxRegisters psxRegs; + +int psxInit() +{ + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + +#ifdef PCSX2_DEVBUILD + Log=0; +#endif + + if (psxMemInit() == -1) return -1; + + return psxCpu->Init(); +} + +void psxReset() { + + psxCpu->Reset(); + + psxMemReset(); + + memset(&psxRegs, 0, sizeof(psxRegs)); + + psxRegs.pc = 0xbfc00000; // Start in bootstrap + + psxRegs.CP0.n.Status = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1 + psxRegs.CP0.n.PRid = 0x0000001f; // PRevID = Revision ID, same as the IOP R3000A + + psxHwReset(); + psxBiosInit(); + psxExecuteBios(); +} + +void psxShutdown() { + psxMemShutdown(); + psxBiosShutdown(); + + psxCpu->Shutdown(); +} + +void psxException(u32 code, u32 bd) { +// PSXCPU_LOG("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); +// SysPrintf("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); + // Set the Cause + psxRegs.CP0.n.Cause &= ~0x7f; + psxRegs.CP0.n.Cause |= code; + +#ifdef PSXCPU_LOG + if (bd) { PSXCPU_LOG("bd set\n"); } +#endif + // Set the EPC & PC + if (bd) { + psxRegs.CP0.n.Cause|= 0x80000000; + psxRegs.CP0.n.EPC = (psxRegs.pc - 4); + } else + psxRegs.CP0.n.EPC = (psxRegs.pc); + + if (psxRegs.CP0.n.Status & 0x400000) + psxRegs.pc = 0xbfc00180; + else + psxRegs.pc = 0x80000080; + + // Set the Status + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) | + ((psxRegs.CP0.n.Status & 0xf) << 2); + + /*if ((((PSXMu32(psxRegs.CP0.n.EPC) >> 24) & 0xfe) == 0x4a)) { + // "hokuto no ken" / "Crash Bandicot 2" ... fix + PSXMu32(psxRegs.CP0.n.EPC)&= ~0x02000000; + }*/ + + if (Config.PsxOut && !CHECK_EEREC) { + u32 call = psxRegs.GPR.n.t1 & 0xff; + switch (psxRegs.pc & 0x1fffff) { + case 0xa0: +#ifdef PSXBIOS_LOG + if (call != 0x28 && call != 0xe) { + PSXBIOS_LOG("Bios call a0: %s (%x) %x,%x,%x,%x\n", biosA0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosA0[call]) + biosA0[call](); + break; + case 0xb0: +#ifdef PSXBIOS_LOG + if (call != 0x17 && call != 0xb) { + PSXBIOS_LOG("Bios call b0: %s (%x) %x,%x,%x,%x\n", biosB0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosB0[call]) + biosB0[call](); + break; + case 0xc0: +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("Bios call c0: %s (%x) %x,%x,%x,%x\n", biosC0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); +#endif + if (biosC0[call]) + biosC0[call](); + break; + } + } + + /*if (psxRegs.CP0.n.Cause == 0x400 && (!(psxHu32(0x1450) & 0x8))) { + hwIntcIrq(1); + }*/ +} + +#define PSX_TESTINT(n, callback) \ + if (psxRegs.interrupt & (1 << n)) { \ + if ((int)(psxRegs.cycle - psxRegs.sCycle[n]) >= psxRegs.eCycle[n]) { \ + if (callback() == 1) { \ + psxRegs.interrupt&= ~(1 << n); \ + } \ + } \ + else if( (int)(g_psxNextBranchCycle - psxRegs.sCycle[n]) > psxRegs.eCycle[n] ) \ + g_psxNextBranchCycle = psxRegs.sCycle[n] + psxRegs.eCycle[n]; \ + } + +static void _psxTestInterrupts() { + PSX_TESTINT(4, psxDma4Interrupt); + PSX_TESTINT(7, psxDma7Interrupt); + + PSX_TESTINT(11, psxDMA11Interrupt); // SIO2 + PSX_TESTINT(12, psxDMA12Interrupt); // SIO2 + PSX_TESTINT(16, sioInterrupt); + PSX_TESTINT(17, cdrInterrupt); + PSX_TESTINT(18, cdrReadInterrupt); + PSX_TESTINT(19, cdvdReadInterrupt); + PSX_TESTINT(20, dev9Interrupt); + PSX_TESTINT(21, usbInterrupt); +} + +#define IOP_WAIT_CYCLE 64 + +void psxBranchTest() +{ + EEsCycle -= (psxRegs.cycle - IOPoCycle) << 3; + IOPoCycle = psxRegs.cycle; + if( EEsCycle > 0 ) + g_psxNextBranchCycle = psxRegs.cycle + min(IOP_WAIT_CYCLE, (EEsCycle>>3)); + else + g_psxNextBranchCycle = psxRegs.cycle; + + if ((int)(psxRegs.cycle - psxNextsCounter) >= psxNextCounter) + psxRcntUpdate(); + + if (psxRegs.interrupt) { + _psxTestInterrupts(); + } + +// if( (int)psxRegs.cycle-(int)g_psxNextBranchCycle > 0 ) +// g_psxNextBranchCycle = psxRegs.cycle+1; +// else + if( (int)(g_psxNextBranchCycle-psxNextsCounter) >= (u32)psxNextCounter ) + g_psxNextBranchCycle = (u32)psxNextsCounter+(u32)psxNextCounter; + + if (psxHu32(0x1078)) { + if(psxHu32(0x1070) & psxHu32(0x1074)){ + if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) { +//#ifdef PSXCPU_LOG +// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074)); +//#endif + psxException(0, 0); + } + } + } +} + +void psxExecuteBios() { +/* while (psxRegs.pc != 0x80030000) + psxCpu->ExecuteBlock(); +#ifdef PSX_LOG + PSX_LOG("*BIOS END*\n"); +#endif*/ +} + +void psxRestartCPU() +{ + psxCpu->Shutdown(); + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + + if (psxCpu->Init() == -1) { + SysClose(); + exit(1); + } + psxCpu->Reset(); +} diff --git a/R3000A.h b/R3000A.h new file mode 100644 index 0000000000..be1f7f4980 --- /dev/null +++ b/R3000A.h @@ -0,0 +1,213 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R3000A_H__ +#define __R3000A_H__ + +#include + +extern u32 g_psxNextBranchCycle; + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*Clear)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R3000Acpu; + +extern R3000Acpu *psxCpu; +extern R3000Acpu psxInt; +extern R3000Acpu psxRec; + +typedef union { + struct { + u32 r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra, hi, lo; // hi needs to be at index 32! don't change + } n; + u32 r[34]; /* Lo, Hi in r[33] and r[32] */ +} GPRRegs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + u32 r[32]; +} CP0Regs; + +typedef struct { + short x, y; +} SVector2D; + +typedef struct { + short z, pad; +} SVector2Dz; + +typedef struct { + short x, y, z, pad; +} SVector3D; + +typedef struct { + short x, y, z, pad; +} LVector3D; + +typedef struct { + unsigned char r, g, b, c; +} CBGR; + +typedef struct { + short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad; +} SMatrix3D; + +typedef union { + struct { + SVector3D v0, v1, v2; + CBGR rgb; + s32 otz; + s32 ir0, ir1, ir2, ir3; + SVector2D sxy0, sxy1, sxy2, sxyp; + SVector2Dz sz0, sz1, sz2, sz3; + CBGR rgb0, rgb1, rgb2; + s32 reserved; + s32 mac0, mac1, mac2, mac3; + u32 irgb, orgb; + s32 lzcs, lzcr; + } n; + u32 r[32]; +} CP2Data; + +typedef union { + struct { + SMatrix3D rMatrix; + s32 trX, trY, trZ; + SMatrix3D lMatrix; + s32 rbk, gbk, bbk; + SMatrix3D cMatrix; + s32 rfc, gfc, bfc; + s32 ofx, ofy; + s32 h; + s32 dqa, dqb; + s32 zsf3, zsf4; + s32 flag; + } n; + u32 r[32]; +} CP2Ctrl; + +typedef struct { + GPRRegs GPR; /* General Purpose Registers */ + CP0Regs CP0; /* Coprocessor0 Registers */ + CP2Data CP2D; /* Cop2 data registers */ + CP2Ctrl CP2C; /* Cop2 control registers */ + u32 pc; /* Program counter */ + u32 code; /* The instruction */ + u32 cycle; + u32 interrupt; + u32 sCycle[64]; + u32 eCycle[64]; + u32 _msflag[32]; + u32 _smflag[32]; +} psxRegisters; + +extern psxRegisters psxRegs; + +#define PSX_IS_CONST1(reg) ((reg)<32 && (g_psxHasConstReg&(1<<(reg)))) +#define PSX_IS_CONST2(reg1, reg2) ((g_psxHasConstReg&(1<<(reg1)))&&(g_psxHasConstReg&(1<<(reg2)))) +#define PSX_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_psxHasConstReg |= (1<<(reg)); \ + g_psxFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define PSX_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_psxHasConstReg &= ~(1<<(reg)); \ +} + +extern u32 g_psxConstRegs[32]; +extern u32 g_psxHasConstReg, g_psxFlushedConstReg; + +#ifndef _PC_ + +#define _i32(x) (s32)x +#define _u32(x) x + +#define _i16(x) (short)x +#define _u16(x) (unsigned short)x + +#define _i8(x) (char)x +#define _u8(x) (unsigned char)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ psxRegs.pc // The next PC to be executed + +#define _Funct_ ((psxRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((psxRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((psxRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((psxRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((psxRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((unsigned short)psxRegs.code) // The immediate part of the instruction register +#define _Target_ (psxRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((short)psxRegs.code) // sign-extended immediate +#define _ImmU_ (psxRegs.code&0xffff) // zero-extended immediate + +#define _rRs_ psxRegs.GPR.r[_Rs_] // Rs register +#define _rRt_ psxRegs.GPR.r[_Rt_] // Rt register +#define _rRd_ psxRegs.GPR.r[_Rd_] // Rd register +#define _rSa_ psxRegs.GPR.r[_Sa_] // Sa register +#define _rFs_ psxRegs.CP0.r[_Rd_] // Fs register + +#define _c2dRs_ psxRegs.CP2D.r[_Rs_] // Rs cop2 data register +#define _c2dRt_ psxRegs.CP2D.r[_Rt_] // Rt cop2 data register +#define _c2dRd_ psxRegs.CP2D.r[_Rd_] // Rd cop2 data register +#define _c2dSa_ psxRegs.CP2D.r[_Sa_] // Sa cop2 data register + +#define _rHi_ psxRegs.GPR.n.hi // The HI register +#define _rLo_ psxRegs.GPR.n.lo // The LO register + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Imm_ * 4) + _PC_) // Calculates the target during a branch instruction +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((short)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; + +#endif + +int psxInit(); +void psxReset(); +void psxShutdown(); +void psxException(u32 code, u32 step); +void psxBranchTest(); +void psxExecuteBios(); +void psxRestartCPU(); + +#endif /* __R3000A_H__ */ diff --git a/R5900.c b/R5900.c new file mode 100644 index 0000000000..db6738ed09 --- /dev/null +++ b/R5900.c @@ -0,0 +1,506 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "Hw.h" +#include "Debug.h" +#include "R3000A.h" +#include "VUmicro.h" + +static int inter; + +__declspec(align(16)) cpuRegisters cpuRegs; +__declspec(align(16)) fpuRegisters fpuRegs; +__declspec(align(16)) tlbs tlb[48]; +__declspec(align(16)) GPR_reg64 g_cpuConstRegs[32] = {0}; +u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0; +R5900cpu *Cpu; + +int EEsCycle; +u32 EEoCycle, IOPoCycle; + +void ExecuteIOP() +{ + psxCpu->ExecuteBlock(); +} + +int cpuInit() +{ + int ret; + extern DWORD dwSaveVersion; + + SysPrintf("PCSX2 v" PCSX2_VERSION " save ver: %x\n", dwSaveVersion); + SysPrintf("Color Legend: White - PCSX2 message\n"); + SysPrintf(COLOR_GREEN " Green - EE sio2 printf\n" COLOR_RESET); + SysPrintf(COLOR_RED " Red - IOP printf\n" COLOR_RESET); + + InitFPUOps(); + cpudetectInit(); + + if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC; + else Config.Options &= ~PCSX2_COP2REC; + + cpuRegs.constzero = 0; + Cpu = CHECK_EEREC ? &recCpu : &intCpu; + + ret = Cpu->Init(); + if (ret == -1 && CHECK_EEREC) { + SysMessage(_("Error initializing Recompiler, switching to Interpreter")); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC); + Cpu = &intCpu; + ret = Cpu->Init(); + } + +#ifdef WIN32_VIRTUAL_MEM + if (memInit() == -1) { + PROCESS_INFORMATION pi; + STARTUPINFO si; + char strdir[255], strexe[255]; + if( MessageBox(NULL, "Failed to allocate enough physical memory to run pcsx2. Try closing\n" + "down background programs, restarting windows, or buying more memory.\n\n" + "Launch TLB version of pcsx2 (pcsx2t.exe)?", "Memory Allocation Error", MB_YESNO) == IDYES ) { + + GetCurrentDirectory(ARRAYSIZE(strdir), strdir); + _snprintf(strexe, ARRAYSIZE(strexe), "%s\\pcsx2t.exe", strdir); + + memset(&si, 0, sizeof(si)); + + if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) { + _snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe); + MessageBox(NULL, strdir, "Failure", MB_OK); + } + else { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + } + + return -1; + } +#endif + if (hwInit() == -1) return -1; + if (vu0Init() == -1) return -1; + if (vu1Init() == -1) return -1; +#ifndef WIN32_VIRTUAL_MEM + if (memInit() == -1) return -1; +#endif + +#ifdef PCSX2_DEVBUILD + Log = 0; +#endif + + return ret; +} + +void cpuReset() { + Cpu->Reset(); + + memReset(); + + memset(&cpuRegs, 0, sizeof(cpuRegs)); + memset(&fpuRegs, 0, sizeof(fpuRegs)); + memset(&tlb, 0, sizeof(tlb)); + + cpuRegs.pc = 0xbfc00000; ///set pc reg to stack + + cpuRegs.CP0.n.Status.val = 0x70400004; //0x10900000 <-- wrong; // COP0 enabled | BEV = 1 | TS = 1 + cpuRegs.CP0.n.PRid = 0x00002e20; // PRevID = Revision ID, same as R5900 + fpuRegs.fprc[0] = 0x00002e00; // fpu Revision.. + fpuRegs.fprc[31] = 0x01000001; // fpu Status/Control + + vu0Reset(); + vu1Reset(); + hwReset(); + vif0Reset(); + vif1Reset(); + rcntInit(); + psxReset(); +} + +void cpuShutdown() +{ + hwShutdown(); +// biosShutdown(); + psxShutdown(); + vu0Shutdown(); + vu1Shutdown(); + memShutdown(); + gsShutdown(); + disR5900FreeSyms(); + + Cpu->Shutdown(); +} + +void cpuException(u32 code, u32 bd) { + u32 offset; + cpuRegs.CP0.n.Cause = code & 0xffff; + + if(cpuRegs.CP0.n.Status.b.ERL == 0){ //Error Level 0-1 + if(((code & 0x7C) >= 0x8) && ((code & 0x7C) <= 0xC)) offset = 0x0; //TLB Refill + else if ((code & 0x7C) == 0x0) offset = 0x200; //Interrupt + else offset = 0x180; // Everything else + + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.BEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } else { //Error Level 2 + SysPrintf("FIX ME: Level 2 cpuException\n"); + if((code & 0x38000) <= 0x8000 ) { //Reset / NMI + cpuRegs.pc = 0xBFC00000; + SysPrintf("Reset request\n"); + UpdateCP0Status(); + return; + } else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter + else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug + else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code); + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.DEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } + UpdateCP0Status(); +} + +void cpuTlbMiss(u32 addr, u32 bd, u32 excode) { + SysPrintf("cpuTlbMiss %x, %x, status=%x, code=%x\n", cpuRegs.pc, cpuRegs.cycle, cpuRegs.CP0.n.Status.val, excode); + if (bd) { + SysPrintf("branch delay!!\n"); + } + cpuRegs.CP0.n.BadVAddr = addr; + cpuRegs.CP0.n.Context &= 0xFF80000F; + cpuRegs.CP0.n.Context |= (addr >> 9) & 0x007FFFF0; + cpuRegs.CP0.n.EntryHi = (addr & 0xFFFFE000) | (cpuRegs.CP0.n.EntryHi & 0x1FFF); + + cpuRegs.CP0.n.Cause = excode; + if (!(cpuRegs.CP0.n.Status.val & 0x2)) { // EXL bit + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + } + + if ((cpuRegs.CP0.n.Status.val & 0x1) == 0) { + cpuRegs.pc = 0x80000000; + } else { + cpuRegs.pc = 0x80000180; + } + + cpuRegs.CP0.n.Status.b.EXL = 1; + UpdateCP0Status(); +// Log=1; varLog|= 0x40000000; +} + +void cpuTlbMissR(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBL); +} + +void cpuTlbMissW(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBS); +} + +void JumpCheckSym(u32 addr, u32 pc) { +#if 0 +// if (addr == 0x80051770) { SysPrintf("Log!: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); Log=1; varLog|= 0x40000000; } + if (addr == 0x8002f150) { SysPrintf("printk: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (addr == 0x8002aba0) return; + if (addr == 0x8002f450) return; + if (addr == 0x800dd520) return; +// if (addr == 0x80049300) SysPrintf("register_blkdev: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (addr == 0x8013cb70) { SysPrintf("change_root: %x\n", cpuRegs.GPR.n.a0.UL[0]); } +// if (addr == 0x8013d1e8) { SysPrintf("Log!\n"); Log++; if (Log==2) exit(0); varLog|= 0x40000000; } +// if (addr == 0x00234e88) { SysPrintf("StoreImage\n"); Log=1; /*psMu32(0x234e88) = 0x03e00008; psMu32(0x234e8c) = 0;*/ } +#endif +/* if ((pc >= 0x00131D50 && + pc < 0x00132454) || + (pc >= 0x00786a90 && + pc < 0x00786ac8))*/ + if (varLog & 0x40000000) { + char *str; + char *strf; + + str = disR5900GetSym(addr); + if (str != NULL) { + strf = disR5900GetUpperSym(pc); + if (strf) { + SysPrintf("Func %8.8x: %s (called by %8.8x: %s)\n", addr, str, pc, strf); + } else { + SysPrintf("Func %8.8x: %s (called by %x)\n", addr, str, pc); + } + if (!strcmp(str, "printf")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (!strcmp(str, "printk")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + } + } +} + +void JumpCheckSymRet(u32 addr) { + if (varLog & 0x40000000) { + char *str; + str = disR5900GetUpperSym(addr); + if (str != NULL) { + SysPrintf("Return : %s, v0=%8.8x\n", str, cpuRegs.GPR.n.v0.UL[0]); + } + } +} + +__inline void _cpuTestMissingINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 && + psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + SysPrintf("*PCSX2*: Error, missing INTC Interrupt\n"); + } + } +} + +__inline void _cpuTestMissingDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 && + (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)) { + if ((cpuRegs.interrupt & (1 << 31)) == 0) { + SysPrintf("*PCSX2*: Error, missing DMAC Interrupt\n"); + } + } +} + +void cpuTestMissingHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestMissingINTC(); + _cpuTestMissingDMAC(); +// _cpuTestTIMR(); + } +} + +#define TESTINT(n, callback) { \ + if ( (cpuRegs.interrupt & (1 << n)) ) { \ + if( ((int)(cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n]) ) { \ + if (callback() == 1) { \ + cpuRegs.interrupt &= ~(1 << n); \ + } \ + } \ + else if( (int)(g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] ) { \ + g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n]; \ + } \ + } \ +} \ + +void _cpuTestInterrupts() { + + inter = cpuRegs.interrupt; + /* These are 'pcsx2 interrupts', they handle asynchronous stuff + that depends on the cycle timings */ + + TESTINT(0, vif0Interrupt); + TESTINT(10, vifMFIFOInterrupt); + TESTINT(1, vif1Interrupt); + TESTINT(11, gifMFIFOInterrupt); + TESTINT(2, gsInterrupt); + TESTINT(3, ipu0Interrupt); + TESTINT(4, ipu1Interrupt); + TESTINT(5, EEsif0Interrupt); + TESTINT(6, EEsif1Interrupt); + TESTINT(8, SPRFROMinterrupt); + TESTINT(9, SPRTOinterrupt); + + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + TESTINT(30, intcInterrupt); + TESTINT(31, dmacInterrupt); +} + +u32 s_iLastCOP0Cycle = 0; +static void _cpuTestTIMR() { + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + + if ( (cpuRegs.CP0.n.Status.val & 0x8000) && + cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) { + SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare); + cpuException(0x808000, cpuRegs.branch); + } +} + +#define EE_WAIT_CYCLE 512 + +// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates +u32 g_nextBranchCycle = 0; +u32 s_lastvsync[2]; +extern u8 g_globalXMMSaved, g_globalMMXSaved; +u32 loaded = 0; + +void cpuBranchTest() +{ + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 0; + +// if( !loaded && cpuRegs.cycle > 0x06000000 ) { +// char strstate[255]; +// sprintf(strstate, "sstates/%8.8x.000", ElfCRC); +// LoadState(strstate); +// loaded = 1; +// } + + g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE; + + if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter) + rcntUpdate(); + + if (cpuRegs.interrupt) + _cpuTestInterrupts(); + + if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter ) + g_nextBranchCycle = nextsCounter+nextCounter; + +//#ifdef CPU_LOG +// cpuTestMissingHwInts(); +//#endif + _cpuTestTIMR(); + + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + psxCpu->ExecuteBlock(); + + if (VU0.VI[REG_VPU_STAT].UL & 0x1) { + Cpu->ExecuteVU0Block(); + } + // don't need in svurec +// if (VU0.VI[REG_VPU_STAT].UL & 0x100) { +// Cpu->ExecuteVU1Block(); +// } + + if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 ) + g_nextBranchCycle = cpuRegs.cycle+1; + + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 1; +} + +static void _cpuTestINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 ){ + if (psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + INT(30,4); + } + } + } +} + +static void _cpuTestDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 ){ + if (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) { + if ( (cpuRegs.interrupt & (1 << 31)) == 0) { + INT(31, 4); + } + } + } +} + +void cpuTestHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + _cpuTestINTC(); + _cpuTestDMAC(); + _cpuTestTIMR(); +} + +void cpuTestINTCInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestINTC(); + } +} + +void cpuTestDMACInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestDMAC(); + } +} + +void cpuTestTIMRInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestTIMR(); + } +} + +extern BOOL bExecBIOS; +void cpuExecuteBios() { + SysPrintf("* PCSX2 *: ExecuteBios\n"); + + bExecBIOS = TRUE; + while (cpuRegs.pc != 0x00200008 && + cpuRegs.pc != 0x00100008) { + Cpu->ExecuteBlock(); + } + + bExecBIOS = FALSE; +// REC_CLEARM(0x00200008); +// REC_CLEARM(0x00100008); +// REC_CLEARM(cpuRegs.pc); + if( CHECK_EEREC ) Cpu->Reset(); + + SysPrintf("* PCSX2 *: ExecuteBios Complete\n"); + GSprintf(5, "PCSX2 v" PCSX2_VERSION "\nExecuteBios Complete\n"); +} + +void cpuRestartCPU() +{ + Cpu = CHECK_EEREC ? &recCpu : &intCpu; + + // restart vus + if (Cpu->Init() == -1) { + SysClose(); + exit(1); + } + + vu0Init(); + vu1Init(); + Cpu->Reset(); + psxRestartCPU(); +} + diff --git a/R5900.h b/R5900.h new file mode 100644 index 0000000000..58340239a8 --- /dev/null +++ b/R5900.h @@ -0,0 +1,276 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R5900_H__ +#define __R5900_H__ + +#include + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Step)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*ExecuteVU0Block)(); /* executes up to a jump */ + void (*ExecuteVU1Block)(); /* executes up to a jump */ + void (*EnableVU0micro)(int enable); + void (*EnableVU1micro)(int enable); + void (*Clear)(u32 Addr, u32 Size); + void (*ClearVU0)(u32 Addr, u32 Size); + void (*ClearVU1)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R5900cpu; + +extern R5900cpu *Cpu; +extern R5900cpu intCpu; +extern R5900cpu recCpu; + +typedef union { // Declare union type GPR register + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} GPR_reg; + +typedef union { + struct { + GPR_reg r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra; + } n; + GPR_reg r[32]; +} GPRregs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare; + union { + struct { + int IE:1; + int EXL:1; + int ERL:1; + int KSU:2; + int unused0:3; + int IM:8; + int EIE:1; + int _EDI:1; + int CH:1; + int unused1:3; + int BEV:1; + int DEV:1; + int unused2:2; + int FR:1; + int unused3:1; + int CU:4; + } b; + u32 val; + } Status; + u32 Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Debug, + DEPC, PerfCnt, ErrCtl, CacheErr, + TagLo, TagHi, ErrorEPC, DESAVE; + } n; + u32 r[32]; +} CP0regs; + +typedef struct { + GPRregs GPR; // GPR regs + // NOTE: don't change order since recompiler uses it + GPR_reg HI; + GPR_reg LO; // hi & log 128bit wide + CP0regs CP0; // is COP0 32bit? + u32 sa; // shift amount (32bit), needs to be 16 byte aligned + u32 constzero; // always 0, for MFSA + u32 pc; // Program counter + u32 code; // The instruction + u32 eCycle[32]; + u32 sCycle[32]; // for internal counters + u32 cycle; // calculate cpucycles.. + u32 interrupt; + int branch; + int opmode; // operating mode + u32 tempcycles; +} cpuRegisters; + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; +extern cpuRegisters cpuRegs; + +// used for optimization +typedef union { + u64 UD[1]; //64 bits + s64 SD[1]; + u32 UL[2]; + s32 SL[3]; + u16 US[4]; + s16 SS[4]; + u8 UC[8]; + s8 SC[8]; +} GPR_reg64; + +#define GPR_IS_CONST1(reg) ((reg)<32 && (g_cpuHasConstReg&(1<<(reg)))) +#define GPR_IS_CONST2(reg1, reg2) ((g_cpuHasConstReg&(1<<(reg1)))&&(g_cpuHasConstReg&(1<<(reg2)))) +#define GPR_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_cpuHasConstReg |= (1<<(reg)); \ + g_cpuFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define GPR_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_cpuHasConstReg &= ~(1<<(reg)); \ +} + +extern GPR_reg64 g_cpuConstRegs[32]; +extern u32 g_cpuHasConstReg, g_cpuFlushedConstReg; + +typedef union { + float f; + u32 UL; +} FPRreg; + +typedef struct { + FPRreg fpr[32]; // 32bit floating point registers + u32 fprc[32]; // 32bit floating point control registers + FPRreg ACC; // 32 bit accumulator +} fpuRegisters; + +extern fpuRegisters fpuRegs; + + +typedef struct { + u32 PageMask,EntryHi; + u32 EntryLo0,EntryLo1; + u32 Mask, nMask; + u32 G; + u32 ASID; + u32 VPN2; + u32 PFN0; + u32 PFN1; +} tlbs; + +extern tlbs tlb[48]; + +#ifndef _PC_ + +#define _i64(x) (s64)x +#define _u64(x) (u64)x + +#define _i32(x) (s32)x +#define _u32(x) (u32)x + +#define _i16(x) (s16)x +#define _u16(x) (u16)x + +#define _i8(x) (s8)x +#define _u8(x) (u8)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ cpuRegs.pc // The next PC to be executed + +#define _Funct_ ((cpuRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((u16)cpuRegs.code) // The immediate part of the instruction register +#define _Target_ (cpuRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((s16)cpuRegs.code) // sign-extended immediate +#define _ImmU_ (cpuRegs.code&0xffff) // zero-extended immediate + + +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Im_ * 4) + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) cpuRegs.GPR.r[x].UD[0] = _PC_ + 4; // Sets the return address in the link register + +#endif + +int cpuInit(); +void cpuReset(); +void cpuShutdown(); +void cpuException(u32 code, u32 bd); +void cpuTlbMissR(u32 addr, u32 bd); +void cpuTlbMissW(u32 addr, u32 bd); +void cpuBranchTest(); +void cpuTestHwInts(); +void cpuTestINTCInts(); +void cpuTestDMACInts(); +void cpuTestTIMRInts(); +void _cpuTestInterrupts(); +void cpuExecuteBios(); +void cpuRestartCPU(); + +u32 VirtualToPhysicalR(u32 addr); +u32 VirtualToPhysicalW(u32 addr); + +void intDoBranch(u32 target); +void intSetBranch(); +void intExecuteVU0Block(); +void intExecuteVU1Block(); + +void JumpCheckSym(u32 addr, u32 pc); +void JumpCheckSymRet(u32 addr); + +// check to see if needs freezing +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeMMXRegs(save) if( g_EEFreezeRegs ) { FreezeMMXRegs_(save); } +#define FreezeXMMRegs(save) if( g_EEFreezeRegs ) { FreezeXMMRegs_(save); } + +//exception code +#define EXC_CODE(x) ((x)<<2) + +#define EXC_CODE_Int EXC_CODE(0) +#define EXC_CODE_Mod EXC_CODE(1) /* TLB Modification exception */ +#define EXC_CODE_TLBL EXC_CODE(2) /* TLB Miss exception (load or instruction fetch) */ +#define EXC_CODE_TLBS EXC_CODE(3) /* TLB Miss exception (store) */ +#define EXC_CODE_AdEL EXC_CODE(4) +#define EXC_CODE_AdES EXC_CODE(5) +#define EXC_CODE_IBE EXC_CODE(6) +#define EXC_CODE_DBE EXC_CODE(7) +#define EXC_CODE_Sys EXC_CODE(8) +#define EXC_CODE_Bp EXC_CODE(9) +#define EXC_CODE_Ri EXC_CODE(10) +#define EXC_CODE_CpU EXC_CODE(11) +#define EXC_CODE_Ov EXC_CODE(12) +#define EXC_CODE_Tr EXC_CODE(13) +#define EXC_CODE_FPE EXC_CODE(15) +#define EXC_CODE_WATCH EXC_CODE(23) +#define EXC_CODE__MASK 0x0000007c +#define EXC_CODE__SHIFT 2 + +#define EXC_TLB_STORE 1 +#define EXC_TLB_LOAD 0 + + +#endif /* __R5900_H__ */ diff --git a/RDebug/deci2.c b/RDebug/deci2.c new file mode 100644 index 0000000000..49add6e2cd --- /dev/null +++ b/RDebug/deci2.c @@ -0,0 +1,26 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +void exchangeSD(DECI2_HEADER *h){ + u8 tmp =h->source; + h->source =h->destination; + h->destination =tmp; +} diff --git a/RDebug/deci2.h b/RDebug/deci2.h new file mode 100644 index 0000000000..80cbe13ca7 --- /dev/null +++ b/RDebug/deci2.h @@ -0,0 +1,66 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2_H__ +#define __DECI2_H__ + +#include "Common.h" +#include "deci2_dcmp.h" +#include "deci2_iloadp.h" +#include "deci2_dbgp.h" +#include "deci2_netmp.h" +#include "deci2_ttyp.h" + +#define PROTO_DCMP 0x0001 +#define PROTO_ITTYP 0x0110 +#define PROTO_IDBGP 0x0130 +#define PROTO_ILOADP 0x0150 +#define PROTO_ETTYP 0x0220 +#define PROTO_EDBGP 0x0230 +#define PROTO_NETMP 0x0400 + + +#pragma pack(1) +typedef struct tag_DECI2_HEADER{ + u16 length, //+00 + _pad, //+02 + protocol; //+04 + char source, //+06 + destination;//+07 +} DECI2_HEADER; //=08 + +typedef struct tag_DECI2_DBGP_BRK{ + u32 address, //+00 + count; //+04 +} DECI2_DBGP_BRK; //=08 +#pragma pack() + +#define STOP 0 +#define RUN 1 + +extern DECI2_DBGP_BRK ebrk[32], ibrk[32]; +extern int ebrk_count, ibrk_count; +extern int runStatus, runCode, runCount; +extern HANDLE runEvent; //i don't like this; +extern int connected; + //when add linux code this might change + +int writeData(char *result); +void exchangeSD(DECI2_HEADER *h); + +#endif//__DECI2_H__ diff --git a/RDebug/deci2.txt b/RDebug/deci2.txt new file mode 100644 index 0000000000..8cf7221c99 --- /dev/null +++ b/RDebug/deci2.txt @@ -0,0 +1,27 @@ +pcsx2 log->debugger tty mapping +ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÑÍÍÍÄÄÄÂÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +Bios ³EE³ 0 ³IOP³ Bios ³ +CPU & MMI & COP0 & FPU ³EE³ 1 ³IOP³ IOP cpu ³ +VU0 & VUMicro ³EE³ 2 ³IOP³ HW ³ +VIF ³EE³ 3 ³IOP³ GTE ³ +GIF ³EE³ 4 ³IOP³ GPU ³ +DMA ³EE³ 5 ³IOP³ DMA ³ +HW & Unknown Memory ³EE³ 6 ³IOP³ Unknown Memory ³ +ELF & Scratch pad ³EE³ 7 ³IOP³ PAD ³ +IPU ³EE³ 8 ³IOP³ CDR ³ +SIF & RPC services ³EE³ 9 ³IOP³ ³ + ³ ³ ³ ³ ³ +SysMessage ³EE³Kernel³IOP³ SysMessage ³ +ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÁÄÄÄÄÄÄÁÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +PRODG: 230,130, 120,121,122,110-119,11F,210-219,21F,410 +CW: 230,130,150,120,121, 210-219,21F,110-119,11F + +0400 PROTO_NETMP +0001 PROTO_DCMP + PROTO_MTWKS +012? PROTO_DRFP (%s) +0230 PROTO_ESDBG +0130 PROTO_ISDBG +011? PROTO_I%dTTY +021? PROTO_E%dTTY + diff --git a/RDebug/deci2_dbgp.c b/RDebug/deci2_dbgp.c new file mode 100644 index 0000000000..5ff8dc54fe --- /dev/null +++ b/RDebug/deci2_dbgp.c @@ -0,0 +1,410 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "VUmicro.h" +#include "deci2.h" + +typedef struct tag_DECI2_DBGP_HEADER{ + DECI2_HEADER h; //+00 + u16 id; //+08 + u8 type, //+0A + code, //+0B + result, //+0C + count; //+0D + u16 _pad; //+0E +} DECI2_DBGP_HEADER; //=10 + +typedef struct tag_DECI2_DBGP_CONF{ + u32 major_ver, //+00 + minor_ver, //+04 + target_id, //+08 + _pad, //+0C + mem_align, //+10 + _pad2, //+14 + reg_size, //+18 + nreg, //+1C + nbrkpt, //+20 + ncont, //+24 + nstep, //+28 + nnext, //+2C + mem_limit_align, //+30 + mem_limit_size, //+34 + run_stop_state, //+38 + hdbg_area_addr, //+3C + hdbg_area_size; //+40 +} DECI2_DBGP_CONF; //=44 + +DECI2_DBGP_CONF +cpu={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu0={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu1={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 32, 1, 0x00, 0x00, 0x07, 0x200, 1, 0x0001E670, 0x100}; +//iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 0, 1, 0x00, 0x00, 0x07, 0x200, 0, 0x00006940, 0x100}; + +#pragma pack(2) +typedef struct tag_DECI2_DBGP_EREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u64 value[2]; //+04 +} DECI2_DBGP_EREG; //=14 + +typedef struct tag_DECI2_DBGP_IREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u32 value; //+04 +} DECI2_DBGP_IREG; //=08 + +typedef struct tag_DECI2_DBGP_MEM{ + u8 space, //+00 + align; //+01 + u16 _pad; //+02 + u32 address; //+04 + u32 length; //+08 +} DECI2_DBGP_MEM; //=0C + +typedef struct tag_DECI2_DBGP_RUN{ + u32 entry, //+00 + gp, //+04 + _pad, //+08 + _pad1, //+0C + argc; //+10 + u32 argv[0]; //+14 +} DECI2_DBGP_RUN; //=14 +#pragma pack() + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy){ + DECI2_DBGP_HEADER *in=(DECI2_DBGP_HEADER*)inbuffer, + *out=(DECI2_DBGP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DBGP_HEADER); + DECI2_DBGP_EREG *eregs=(DECI2_DBGP_EREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_IREG *iregs=(DECI2_DBGP_IREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_MEM *mem =(DECI2_DBGP_MEM*) ((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_RUN *run =(DECI2_DBGP_RUN*) ((u8*)in+sizeof(DECI2_DBGP_HEADER)); + static char line[1024]; + int i, s; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + //out->h.length=sizeof(DECI2_DBGP_HEADER); + out->type++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->type){ + case 0x00://ok + sprintf(line, "%s/GETCONF", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I'){ + memcpy(data, &iop, sizeof(DECI2_DBGP_CONF)); + }else + switch(in->id){ + case 0:memcpy(data, &cpu, sizeof(DECI2_DBGP_CONF));break; + case 1:memcpy(data, &vu0, sizeof(DECI2_DBGP_CONF));break; + case 2:memcpy(data, &vu1, sizeof(DECI2_DBGP_CONF));break; + } + break; + case 0x02://ok + sprintf(line, "%s/2", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + break; + case 0x04://ok + sprintf(line, "%s/GETREG count=%d kind[0]=%d number[0]=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:iregs[i].value=psxRegs.GPR.n.lo;break; + case 1:iregs[i].value=psxRegs.GPR.n.hi;break; + } + break; + case 2:iregs[i].value=psxRegs.GPR.r[iregs[i].number]; break; + case 3: + if (iregs[i].number==14) psxRegs.CP0.n.EPC=psxRegs.pc; + iregs[i].value=psxRegs.CP0.r[iregs[i].number]; + break; + case 6:iregs[i].value=psxRegs.CP2D.r[iregs[i].number]; break; + case 7:iregs[i].value=psxRegs.CP2C.r[iregs[i].number]; break; + default: + iregs[0].value++;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(eregs[i].value, &cpuRegs.GPR.r[eregs[i].number], 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(eregs[i].value, &cpuRegs.HI.UD[0], 8);break; + case 1:memcpy(eregs[i].value, &cpuRegs.LO.UD[0], 8);break; + case 2:memcpy(eregs[i].value, &cpuRegs.HI.UD[1], 8);break; + case 3:memcpy(eregs[i].value, &cpuRegs.LO.UD[1], 8);break; + case 4:memcpy(eregs[i].value, &cpuRegs.sa, 4); break; + } + case 2: + if (eregs[i].number==14) cpuRegs.CP0.n.EPC=cpuRegs.pc; + memcpy(eregs[i].value, &cpuRegs.CP0.r[eregs[i].number], 4); + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(eregs[i].value, &fpuRegs.fpr[eregs[i].number], 4);break; + case 6:memcpy(eregs[i].value, &fpuRegs.fprc[eregs[i].number], 4);break; + case 7:memcpy(eregs[i].value, &VU0.VF[eregs[i].number], 16);break; + case 8:memcpy(eregs[i].value, &VU0.VI[eregs[i].number], 4);break; + case 9:memcpy(eregs[i].value, &VU1.VF[eregs[i].number], 16);break; + case 10:memcpy(eregs[i].value, &VU1.VI[eregs[i].number], 4);break; + default: + eregs[0].value[0]++;//dummy; might be assert(0) + } + break; + case 0x06://ok + sprintf(line, "%s/PUTREG count=%d kind[0]=%d number[0]=%d value=%016I64X_%016I64X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number, eregs[0].value[1], eregs[0].value[0]); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:psxRegs.GPR.n.lo=iregs[i].value;break; + case 1:psxRegs.GPR.n.hi=iregs[i].value;break; + } + break; + case 2:psxRegs.GPR.r[iregs[i].number]=iregs[i].value; break; + case 3: + psxRegs.CP0.r[iregs[i].number]=iregs[i].value; + if (iregs[i].number==14) psxRegs.pc=psxRegs.CP0.n.EPC; + break; + case 6:psxRegs.CP2D.r[iregs[i].number]=iregs[i].value; break; + case 7:psxRegs.CP2C.r[iregs[i].number]=iregs[i].value; break; + default: + ;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(&cpuRegs.GPR.r[eregs[i].number], eregs[i].value, 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(&cpuRegs.HI.UD[0], eregs[i].value, 8);break; + case 1:memcpy(&cpuRegs.LO.UD[0], eregs[i].value, 8);break; + case 2:memcpy(&cpuRegs.HI.UD[1], eregs[i].value, 8);break; + case 3:memcpy(&cpuRegs.LO.UD[1], eregs[i].value, 8);break; + case 4:memcpy(&cpuRegs.sa, eregs[i].value, 4); break; + } + break; + case 2: + memcpy(&cpuRegs.CP0.r[eregs[i].number], eregs[i].value, 4); + if (eregs[i].number==14) cpuRegs.pc=cpuRegs.CP0.n.EPC; + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(&fpuRegs.fpr[eregs[i].number], eregs[i].value, 4);break; + case 6:memcpy(&fpuRegs.fprc[eregs[i].number], eregs[i].value, 4);break; + case 7:memcpy(&VU0.VF[eregs[i].number], eregs[i].value, 16);break; + case 8:memcpy(&VU0.VI[eregs[i].number], eregs[i].value, 4);break; + case 9:memcpy(&VU1.VF[eregs[i].number], eregs[i].value, 16);break; + case 10:memcpy(&VU1.VI[eregs[i].number], eregs[i].value, 4);break; + default: + ;//dummy; might be assert(0) + } + break; + case 0x08://ok + sprintf(line, "%s/RDMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)out+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSXM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(data, PSM(mem->address), mem->length); + else + if ((((mem->address & 0x1FFFFFFF)>128*1024*1024) || ((mem->address & 0x1FFFFFFF)<32*1024*1024)) && PSM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(data, &VU0.Mem[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Mem[mem->address & 0x3FFF], mem->length); + break; + case 2: + if (in->id==1) + memcpy(data, &VU0.Micro[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Micro[mem->address & 0x3FFF], mem->length); + break; + } + out->h.length=mem->length+data-(u8*)out; + break; + case 0x0a://ok + sprintf(line, "%s/WRMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)in+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if (mem->length==4 && *(int*)data==0x0000000D) + strcat(line, " BREAKPOINT"); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(PSXM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(PSM(mem->address), data, mem->length); + else + if (PSM(mem->address & 0x1FFFFFFF)) + memcpy(PSM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(&VU0.Mem[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Mem[mem->address & 0x3FFF], data, mem->length); + break; + case 2: + if (in->id==1) + memcpy(&VU0.Micro[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Micro[mem->address & 0x3FFF], data, mem->length); + break; + } + out->h.length=sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM); + break; + case 0x10://ok + sprintf(line, "%s/GETBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I') memcpy(data, ibrk, out->count=ibrk_count); + else memcpy(data, ebrk, out->count=ebrk_count); + out->h.length=sizeof(DECI2_DBGP_HEADER)+out->count*sizeof(DECI2_DBGP_BRK); + break; + case 0x12://ok [does not break on iop brkpts] + sprintf(line, "%s/PUTBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + out->h.length=sizeof(DECI2_DBGP_HEADER); + if (in->count>32){ + out->result=1; + strcat(line, "TOO MANY"); + break; + } + if (in->h.destination=='I') memcpy(ibrk, data, ibrk_count=in->count); + else memcpy(ebrk, data, ebrk_count=in->count); + out->count=0; + break; + case 0x14://ok, [w/o iop] + sprintf(line, "%s/BREAK count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + if (in->h.destination=='I') + ; + else{ + out->result = ( InterlockedExchange(&runStatus, STOP)==STOP ? + 0x20 : 0x21 ); + out->code=0xFF; + Sleep(50); + } + break; + case 0x16://ok, [w/o iop] + sprintf(line, "%s/CONTINUE code=%s count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", + in->code==0?"CONT":in->code==1?"STEP":"NEXT", in->count); + if (in->h.destination=='I') + ; + else{ + InterlockedExchange(&runStatus, STOP); + Sleep(100);//first get the run thread to Wait state + runCount=in->count; + runCode=in->code; + SetEvent(runEvent);//kick it + } + break; + case 0x18://ok [without argc/argv stuff] + sprintf(line, "%s/RUN code=%d count=%d entry=0x%08X gp=0x%08X argc=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->code, in->count, + run->entry, run->gp, run->argc); + cpuRegs.CP0.n.EPC=cpuRegs.pc=run->entry; + cpuRegs.GPR.n.gp.UL[0]=run->gp; +// threads_array[0].argc = run->argc; + for (i=0, s=0; i<(int)run->argc; i++) s+=run->argv[i]; + memcpy(PSM(0), &run->argv[run->argc], s); +// threads_array[0].argstring = 0; + InterlockedExchange(&runStatus, STOP); + Sleep(1000);//first get the run thread to Wait state + runCount=0; + runCode=0xFF; + SetEvent(runEvent);//awake it + out->h.length=sizeof(DECI2_DBGP_HEADER); + break; + default: + sprintf(line, "type=0x%02X code=%d count=%d [unknown]", in->type, in->code, in->count); + } + sprintf(message, "[DBGP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + sprintf(eepc, "%08X", cpuRegs.pc); + sprintf(ioppc, "%08X", psxRegs.pc); + sprintf(eecy, "%d", cpuRegs.cycle); + sprintf(iopcy, "%d", psxRegs.cycle); + writeData(outbuffer); +} + +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count){ + static DECI2_DBGP_HEADER tmp; + tmp.h.length =sizeof(DECI2_DBGP_HEADER); + tmp.h._pad =0; + tmp.h.protocol =( source=='E' ? PROTO_EDBGP : PROTO_IDBGP ); + tmp.h.source =source; + tmp.h.destination='H'; + tmp.id =id; + tmp.type =0x15; + tmp.code =code; + tmp.result =result; + tmp.count =count; + tmp._pad =0; + writeData((char*)&tmp); +} diff --git a/RDebug/deci2_dbgp.h b/RDebug/deci2_dbgp.h new file mode 100644 index 0000000000..ab28c21c95 --- /dev/null +++ b/RDebug/deci2_dbgp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DBGP_H__ +#define __DECI2DBGP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy); +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count); + +#endif//__DECI2DBGP_H__ diff --git a/RDebug/deci2_dcmp.c b/RDebug/deci2_dcmp.c new file mode 100644 index 0000000000..9348040ea4 --- /dev/null +++ b/RDebug/deci2_dcmp.c @@ -0,0 +1,83 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +typedef struct tag_DECI2_DCMP_CONNECT{ + u8 result, //+00 + _pad[3];//+01 + u64 EEboot, //+04 + IOPboot;//+0C +} DECI2_DCMP_CONNECT; //=14 + +typedef struct tag_DECI2_DCMP_ECHO{ + u16 identifier, //+00 + sequence; //+02 + u8 data[32]; //+04 +} DECI2_DCMP_ECHO; //=24 + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + DECI2_DCMP_CONNECT *connect=(DECI2_DCMP_CONNECT*)data; + DECI2_DCMP_ECHO *echo =(DECI2_DCMP_ECHO*)data; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ +/* case 0: + sprintf(message, " [DCMP] type=CONNECT code=%s EEboot=0x%I64X IOP=0x%I64X", + in->code==0?"CONNECT":"DISCONNECT", connect->EEboot, connect->IOPboot); + data=(u8*)out+sizeof(DECI2_DCMP_HEADER); + connect=(DECI2_DCMP_CONNECT*)data; + connect->result=0; + break; + case 1: + sprintf(message, " [DCMP] type=ECHO id=%X seq=%X", echo->identifier, echo->sequence); + exchangeSD(&out->h); + break; +// not implemented, not needed? + default: + sprintf(message, " [DCMP] type=%d[unknown]", in->type); +*/ } + out->code++; +} + +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size){ + static char tmp[100]; + ((DECI2_DCMP_HEADER*)tmp)->h.length =sizeof(DECI2_DCMP_HEADER)+size; + ((DECI2_DCMP_HEADER*)tmp)->h._pad =0; + ((DECI2_DCMP_HEADER*)tmp)->h.protocol =protocol; + ((DECI2_DCMP_HEADER*)tmp)->h.source =source; + ((DECI2_DCMP_HEADER*)tmp)->h.destination=destination; + ((DECI2_DCMP_HEADER*)tmp)->type =type; + ((DECI2_DCMP_HEADER*)tmp)->code =code; + ((DECI2_DCMP_HEADER*)tmp)->_pad =0; + memcpy(&tmp[sizeof(DECI2_DCMP_HEADER)], data, size); + writeData(tmp); +} \ No newline at end of file diff --git a/RDebug/deci2_dcmp.h b/RDebug/deci2_dcmp.h new file mode 100644 index 0000000000..18e2c80245 --- /dev/null +++ b/RDebug/deci2_dcmp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DCMP_H__ +#define __DECI2DCMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message); +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size); + +#endif//__DECI2DCMP_H__ diff --git a/RDebug/deci2_drfp.c b/RDebug/deci2_drfp.c new file mode 100644 index 0000000000..dff6076e1a --- /dev/null +++ b/RDebug/deci2_drfp.c @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ + case 4://[OK] + sprintf(message, " [DCMP] code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + break; + default: + sprintf(message, " [DCMP] code=%d[unknown] result=%d", netmp->code, netmp->result); + } + result->code++; + result->result=0; //ok +} diff --git a/RDebug/deci2_drfp.h b/RDebug/deci2_drfp.h new file mode 100644 index 0000000000..eb9097092c --- /dev/null +++ b/RDebug/deci2_drfp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DRFP_H__ +#define __DECI2DRFP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2DRFP_H__ \ No newline at end of file diff --git a/RDebug/deci2_iloadp.c b/RDebug/deci2_iloadp.c new file mode 100644 index 0000000000..d761e8bd12 --- /dev/null +++ b/RDebug/deci2_iloadp.c @@ -0,0 +1,106 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "PsxBios2.h" +#include "deci2.h" + +typedef struct tag_DECI2_ILOADP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 cmd + action, //+09 + result, //+0A + stamp; //+0B + u32 moduleId; //+0C +} DECI2_ILOADP_HEADER; //=10 + +typedef struct tag_DECI2_ILOADP_INFO{ + u16 version, //+00 + flags; //+02 + u32 module_address, //+04 + text_size, //+08 + data_size, //+0C + bss_size, //+10 + _pad[3]; //+14 +} DECI2_ILOADP_INFO; + +void writeInfo(DECI2_ILOADP_INFO *info, + u16 version, u16 flags, u32 module_address, + u32 text_size, u32 data_size, u32 bss_size){ + info->version =version; + info->flags =flags; + info->module_address=module_address; + info->text_size =text_size; + info->data_size =data_size; + info->bss_size =bss_size; + info->_pad[0]=info->_pad[1]=info->_pad[2]=0; +} + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message){ + DECI2_ILOADP_HEADER *in=(DECI2_ILOADP_HEADER*)inbuffer, + *out=(DECI2_ILOADP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_ILOADP_HEADER); + irxImageInfo *iii; + static char line[1024]; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_ILOADP_HEADER); + out->code++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->code){ + case 0: + sprintf(line, "code=START action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 2: + sprintf(line, "code=REMOVE action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 4: + sprintf(line, "code=LIST action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for (iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0, data+=4) + *(u32*)data=iii->index; + + out->h.length=data-(u8*)out; + break; + case 6: + sprintf(line, "code=INFO action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for(iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0) + if (iii->index==in->moduleId){ + writeInfo((DECI2_ILOADP_INFO*)data, + iii->version, iii->flags, iii->vaddr, iii->text_size, iii->data_size, iii->bss_size); + data+=sizeof(DECI2_ILOADP_INFO); + strcpy(data, PSXM(iii->name)); + data+=strlen(PSXM(iii->name))+4; + data=(char*)((int)data & 0xFFFFFFFC); + break; + + } + out->h.length=data-(u8*)out; + break; + case 8: + sprintf(line, "code=WATCH action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + default: + sprintf(line, "code=%d[unknown]", in->code); + } + sprintf(message, "[ILOADP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + writeData(outbuffer); +} diff --git a/RDebug/deci2_iloadp.h b/RDebug/deci2_iloadp.h new file mode 100644 index 0000000000..a55b046e04 --- /dev/null +++ b/RDebug/deci2_iloadp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2ILOADP_H__ +#define __DECI2ILOADP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2ILOADP_H__ diff --git a/RDebug/deci2_netmp.c b/RDebug/deci2_netmp.c new file mode 100644 index 0000000000..472dfc571c --- /dev/null +++ b/RDebug/deci2_netmp.c @@ -0,0 +1,134 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_NETMP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 + result; //+09 +} DECI2_NETMP_HEADER; //=0A + +typedef struct tag_DECI2_NETMP_CONNECT{ + u8 priority, //+00 + _pad; //+01 + u16 protocol; //+02 +} DECI2_NETMP_CONNECT; //=04 + +char d2_message[100]; +int d2_count=1; +DECI2_NETMP_CONNECT d2_connect[50]={0xFF, 0, 0x400}; + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_NETMP_HEADER *in=(DECI2_NETMP_HEADER*)inbuffer, + *out=(DECI2_NETMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_NETMP_HEADER); + DECI2_NETMP_CONNECT *connect=(DECI2_NETMP_CONNECT*)data; //connect + int i, n; + static char p[100], line[1024]; + u64 EEboot, IOPboot; //reset + u16 node; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_NETMP_HEADER); + out->code++; + out->result=0; //ok + switch(in->code){ + case 0: + n=(in->h.length-sizeof(DECI2_NETMP_HEADER)) / sizeof(DECI2_NETMP_CONNECT); + sprintf(line, "code=CONNECT"); + for (i=0; ih.length=data-(u8*)out; + writeData(outbuffer); + + node=(u16)'I'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=(u16)'E'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=PROTO_ILOADP; + sendDCMP(PROTO_DCMP, 'I', 'H', 2, 1, (char*)&node, sizeof(node)); + + for (i=0; i<10; i++){ + node=PROTO_ETTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + } + node=PROTO_ETTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + break; + case 4://[OK] + sprintf(line, "code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + writeData(outbuffer); + break; + case 6://[ok] + sprintf(line, "code=STATUS"); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER)+2; + /* + memcpy(data, d2_connect, 1*sizeof(DECI2_NETMP_CONNECT)); + data+=1*sizeof(DECI2_NETMP_CONNECT); + *(u32*)data=1;//quite fast;) + data+=4; + memcpy(data, d2_message, strlen(d2_message)); + data+=strlen(d2_message); + *(u32*)data=0;//null end the string on a word boundary + data+=3;data=(u8*)((int)data & 0xFFFFFFFC);*/ + + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + case 8: + sprintf(line, "code=KILL protocol=0x%04X", *(u16*)data); + writeData(outbuffer); + break; + case 10: + sprintf(line, "code=VERSION %s", data); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER); + strcpy(data, "0.2.0");data+=strlen("0.2.0");//emu version;) + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + default: + sprintf(line, "code=%d[unknown] result=%d", in->code, in->result); + writeData(outbuffer); + } + sprintf(message, "[NETMP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); +} diff --git a/RDebug/deci2_netmp.h b/RDebug/deci2_netmp.h new file mode 100644 index 0000000000..7440278251 --- /dev/null +++ b/RDebug/deci2_netmp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2NETMP_H__ +#define __DECI2NETMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2NETMP_H__ diff --git a/RDebug/deci2_ttyp.c b/RDebug/deci2_ttyp.c new file mode 100644 index 0000000000..ce66e2fb08 --- /dev/null +++ b/RDebug/deci2_ttyp.c @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_TTYP_HEADER{ + DECI2_HEADER h; //+00 + u32 flushreq; //+08 + u8 data[0]; //+0C +} DECI2_TTYP_HEADER; //=0C + +void sendTTYP(u16 protocol, u8 source, char *data){ + static char tmp[2048]; + ((DECI2_TTYP_HEADER*)tmp)->h.length =sizeof(DECI2_TTYP_HEADER)+strlen(data); + ((DECI2_TTYP_HEADER*)tmp)->h._pad =0; + ((DECI2_TTYP_HEADER*)tmp)->h.protocol =protocol +(source=='E' ? PROTO_ETTYP : PROTO_ITTYP); + ((DECI2_TTYP_HEADER*)tmp)->h.source =source; + ((DECI2_TTYP_HEADER*)tmp)->h.destination='H'; + ((DECI2_TTYP_HEADER*)tmp)->flushreq =0; + if (((DECI2_TTYP_HEADER*)tmp)->h.length>2048) + SysMessage("TTYP: Buffer overflow"); + else + memcpy(&tmp[sizeof(DECI2_TTYP_HEADER)], data, strlen(data)); + //writeData(tmp); +} \ No newline at end of file diff --git a/RDebug/deci2_ttyp.h b/RDebug/deci2_ttyp.h new file mode 100644 index 0000000000..8d27146cec --- /dev/null +++ b/RDebug/deci2_ttyp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2TTYP_H__ +#define __DECI2TTYP_H__ + +#include "Common.h" +#include "deci2.h" + +//void D2_(char *inbuffer, char *outbuffer, char *message); +void sendTTYP(u16 protocol, u8 source, char *data); + +#endif//__DECI2TTYP_H__ diff --git a/RDebug/iloadp.txt b/RDebug/iloadp.txt new file mode 100644 index 0000000000..c8b6c68834 --- /dev/null +++ b/RDebug/iloadp.txt @@ -0,0 +1,32 @@ +ILOADP_MODULE_INFO{ + u16 flags ÄÄÄÄ¿ <ÄÄÄ¿ + u16 version <ÄÄÄÙ ÄÄÄÄÙ + u32 addr + u32 sz_text + u32 sz_data + u32 sz_bss + u32 reserved1 + u32 reserved2 + u32 reserved3 + u8* name +}; + +ILOADP_HDR{ + u8 cmd + u8 action + u8 result + u8 stamp + u32 module_id +}; + +ILOADP_START(cmd==00) +------------------------------------------ +ILOADP_HDR_START{ + ILOADP_HDR hdr //+00 + u8* modulename //+10 //asciiz +}; //=10+strlen(modulename)+1 +action 0D(IOP_LOAD_IRX) +modulename host:E:\TEMP2\GCC\share\SIO2D.IRX + +action 02(IOP_RUN) +modulename E:\TEMP2\GCC\share\SIO2D.IRX param diff --git a/SPR.c b/SPR.c new file mode 100644 index 0000000000..0b3a7ddc45 --- /dev/null +++ b/SPR.c @@ -0,0 +1,385 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "SPR.h" + +#include "ir5900.h" + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +#define spr1 ((DMACh*)&PS2MEM_HW[0xD400]) + +void sprInit() { +} + +//__inline static void SPR0transfer(u32 *data, int size) { +///* while (size > 0) { +//#ifdef SPR_LOG +// SPR_LOG("SPR1transfer: %x\n", *data); +//#endif +// data++; size--; +// }*/ +// size <<= 2; +// if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO +// (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO +// hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } else { +// u32 * p = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; +// //WriteCodeSSE2(p,data,size >> 4); +// memcpy_amd((u8*)data, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } +// spr0->sadr+= size; +//} + +static void TestClearVUs(u32 madr, u32 size) +{ + if( madr >= 0x11000000 ) { + if( madr < 0x11004000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu0\n"); +#endif + Cpu->ClearVU0(madr&0xfff, size); + } + else if( madr >= 0x11008000 && madr < 0x1100c000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu1\n"); +#endif + Cpu->ClearVU1(madr&0x3fff, size); + } + } +} + +int _SPR0chain() { + u32 qwc = spr0->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr0->madr); + if (pMem == NULL) return -1; + + //SPR0transfer(pMem, qwc << 2); + qwc <<= 4; + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + spr0->madr = psHu32(DMAC_RBOR) + ((spr0->madr + qwc) & (psHu32(DMAC_RBSR))); //Wrap MADR + } else { + Cpu->Clear(spr0->madr, qwc>>2); + // clear VU mem also! + TestClearVUs(spr0->madr, qwc>>2); + + memcpy_amd((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + spr0->madr += qwc; + } + spr0->sadr += qwc; + + spr0->qwc = 0; + return (qwc>>4) * BIAS; // bus is 1/2 the ee speed +} + +#define SPR0chain() \ + if (spr0->qwc) { \ + cycles += _SPR0chain(); \ +/* cycles+= spr0->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR0interleave() { + int qwc = spr0->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + //SysPrintf("dmaSPR0 interleave\n"); + + while (qwc > 0) { + spr0->qwc = min(tqwc, qwc); qwc-= spr0->qwc; + pMem = (u32*)dmaGetAddr(spr0->madr); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } else { + Cpu->Clear(spr0->madr, spr0->qwc<<2); + // clear VU mem also! + TestClearVUs(spr0->madr, qwc>>2); + + memcpy_amd((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } + cycles += tqwc * BIAS; + spr0->sadr+= spr0->qwc * 16; + spr0->madr+= (sqwc+spr0->qwc)*16; //qwc-= sqwc; + } + + spr0->qwc = 0; + INT(8, cycles); +} + +void _dmaSPR0() { + u32 *ptag; + int id; + int cycles = 0; + int done = 0; + + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR0 stall %d\n", (psHu32(DMAC_CTRL)>>6)&3); + } + + if ((spr0->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR0interleave(); + return; + } + + // Transfer Dn_QWC from SPR to Dn_MADR + SPR0chain(); + + + if ((spr0->chcr & 0xc) == 0) { // Normal Mode + + INT(8, cycles); + + return; + } + + // Destination Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; + spr0->sadr+= 16; + + // Transfer dma tag if tte is set +// if (spr0->chcr & 0x40) SPR0transfer(ptag, 4); + + spr0->chcr = ( spr0->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr0->madr = ptag[1]; //MADR = ADDR field + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr0->qwc, id, spr0->madr); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR stall control\n"); + } + + switch (id) { + case 0: // CNTS - Transfer QWC following the tag (Stall Control) + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20 ) psHu32(DMAC_STADR) = spr0->madr; //Copy MADR to DMAC_STADR stall addr register + break; + + case 1: // CNT - Transfer QWC following the tag. + break; + + case 7: // End - Transfer QWC following the tag + done = 1; //End Transfer + break; + } + SPR0chain(); + if (spr0->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag + //SysPrintf("SPR0 TIE\n"); + done = 1; + spr0->qwc = 0; + break; + } + + +/* if (spr0->chcr & 0x80 && ptag[0] >> 31) { +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return; + }*/ + } + + INT(8, cycles); + +} + +int SPRFROMinterrupt() +{ + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return 1; +} + +void dmaSPR0() { // fromSPR + int qwc = spr0->qwc; +#ifdef SPR_LOG + SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx\n", + spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); +#endif + + _dmaSPR0(); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) { // GIF MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & (psHu32(DMAC_RBSR))); + mfifoGIFtransfer(qwc); + } else + if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & (psHu32(DMAC_RBSR))); + mfifoVIF1transfer(qwc); + } + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +__inline static void SPR1transfer(u32 *data, int size) { +/* { + int i; + for (i=0; isadr+i*4) & 0x3fff, data[i] ); +#endif + } + }*/ + //Cpu->Clear(spr1->sadr, size); // why? + memcpy_amd(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)data, size << 2); + + spr1->sadr+= size << 2; +} + +int _SPR1chain() { + u32 qwc = spr1->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr1->madr); + if (pMem == NULL) return -1; + + SPR1transfer(pMem, qwc << 2); + spr1->madr+= spr1->qwc << 4; + spr1->qwc = 0; + return (qwc) * BIAS; +} + +#define SPR1chain() \ + if (spr1->qwc) { \ + cycles += _SPR1chain(); \ +/* cycles+= spr1->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR1interleave() { + int qwc = spr1->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + + //SysPrintf("dmaSPR1 interleave\n"); + + while (qwc > 0) { + spr1->qwc = min(tqwc, qwc); qwc-= spr1->qwc; + pMem = (u32*)dmaGetAddr(spr1->madr); + SPR1transfer(pMem, spr1->qwc << 2); + cycles += spr1->qwc * BIAS; + spr1->madr+= (sqwc + spr1->qwc) * 16; //qwc-= sqwc; + } + + spr1->qwc = 0; + INT(9, cycles); + +} + +void dmaSPR1() { // toSPR + u32 *ptag; + int id, done=0; + int cycles = 0; + +#ifdef SPR_LOG + SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n" + " tadr = 0x%x, sadr = 0x%x\n", + spr1->chcr, spr1->madr, spr1->qwc, + spr1->tadr, spr1->sadr); +#endif + + if ((spr1->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR1interleave(); + FreezeMMXRegs(0); + return; + } + + // Transfer Dn_QWC from Dn_MADR to SPR1 + SPR1chain(); + + if ((spr1->chcr & 0xc) == 0) { // Normal Mode + + INT(9, cycles); + FreezeMMXRegs(0); + return; + } + + // Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + + // Transfer dma tag if tte is set + if (spr1->chcr & 0x40) { +#ifdef SPR_LOG + SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + SPR1transfer(ptag, 4); //Transfer Tag + } + + spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr1->madr = ptag[1]; //MADR = ADDR field + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr1->qwc, id, spr1->madr); +#endif + + done = hwDmacSrcChain(spr1, id); + SPR1chain(); //Transfers the data set by the switch + + if (spr1->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("SPR1 TIE\n"); + spr1->qwc = 0; + break; + } + } + + + INT(9, cycles); + FreezeMMXRegs(0); +} + +int SPRTOinterrupt() +{ + spr1->chcr &= ~0x100; + hwDmacIrq(9); + return 1; +} + diff --git a/SPR.h b/SPR.h new file mode 100644 index 0000000000..7ae0a57b8a --- /dev/null +++ b/SPR.h @@ -0,0 +1,29 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SPR_H__ +#define __SPR_H__ + +#include "Common.h" + +void sprInit(); +void dmaSPR0(); +void dmaSPR1(); +int SPRFROMinterrupt(); +int SPRTOinterrupt(); +#endif /* __SPR_H__ */ diff --git a/Sif.c b/Sif.c new file mode 100644 index 0000000000..51701f724c --- /dev/null +++ b/Sif.c @@ -0,0 +1,616 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "Common.h" +#include "PsxCommon.h" +#include "Sif.h" +#include "Sifcmd.h" + +#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000]) +#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400]) +#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800]) + +#define FIFO_SIF0_W 128 +#define FIFO_SIF1_W 128 + +typedef struct { + u32 fifoData[FIFO_SIF0_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; + struct sifData sifData; +} _sif0; + +typedef struct { + u32 fifoData[FIFO_SIF1_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; +} _sif1; + +_sif0 sif0; +_sif1 sif1; + +int sifInit() { + memset(&sif0, 0, sizeof(sif0)); + memset(&sif1, 0, sizeof(sif1)); + + return 0; +} + +void SIF0write(u32 *from, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoWritePos)) { + int wP0 = (FIFO_SIF0_W-sif0.fifoWritePos); + int wP1 = words - wP0; + memcpy_amd(&sif0.fifoData[sif0.fifoWritePos], from, wP0 << 2); + memcpy_amd(&sif0.fifoData[0], &from[wP0], wP1 << 2); + sif0.fifoWritePos = wP1; + } + else + { + memcpy_amd(&sif0.fifoData[sif0.fifoWritePos], from, words << 2); + sif0.fifoWritePos += words; + } + + sif0.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 + %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoWritePos); +#endif + +/* if (sif0.fifoSize == FIFO_SIF0_W) { + Cpu->ExecuteBlock(); + }*/ +} + +void SIF0read(u32 *to, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoReadPos)) + { + int wP0 = (FIFO_SIF0_W-sif0.fifoReadPos); + int wP1 = words - wP0; + memcpy_amd(to, &sif0.fifoData[sif0.fifoReadPos], wP0 << 2); + memcpy_amd(&to[wP0], &sif0.fifoData[0], wP1 << 2); + sif0.fifoReadPos = wP1; + } + else + { + memcpy_amd(to, &sif0.fifoData[sif0.fifoReadPos], words << 2); + sif0.fifoReadPos += words; + } + + sif0.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 - %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoReadPos); +#endif +} + +void SIF1write(u32 *from, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoWritePos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoWritePos); + int wP1 = words - wP0; + memcpy_amd(&sif1.fifoData[sif1.fifoWritePos], from, wP0 << 2); + memcpy_amd(&sif1.fifoData[0], &from[wP0], wP1 << 2); + sif1.fifoWritePos = wP1; + } + else + { + memcpy_amd(&sif1.fifoData[sif1.fifoWritePos], from, words << 2); + sif1.fifoWritePos += words; + } + + sif1.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 + %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoWritePos); +#endif + +/* if (sif1.fifoSize == FIFO_SIF1_W) { + psxCpu->ExecuteBlock(); + }*/ +} + +void SIF1read(u32 *to, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoReadPos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoReadPos); + int wP1 = words - wP0; + memcpy_amd(to, &sif1.fifoData[sif1.fifoReadPos], wP0 << 2); + memcpy_amd(&to[wP0], &sif1.fifoData[0], wP1 << 2); + sif1.fifoReadPos = wP1; + } + else + { + memcpy_amd(to, &sif1.fifoData[sif1.fifoReadPos], words << 2); + sif1.fifoReadPos += words; + } + + sif1.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 - %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoReadPos); +#endif +} + +void SIF0Dma() +{ + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + +#ifdef SIF_LOG + SIF_LOG("SIF0 DMA start...\n"); +#endif + + do + { + notDone = 0; + + if(HW_DMA9_CHCR & 0x01000000) // If EE SIF0 is enabled + { + int size = sif0.counter; //HW_DMA9_BCR >> 16; + + if(size == 0) // If there's no more to transfer + { + // Note.. add normal mode here + if (sif0.sifData.data & 0xC0000000) // If NORMAL mode or end of CHAIN, or interrupt then stop DMA + { +#ifdef SIF_LOG + SIF_LOG(" IOP SIF Stopped\n"); +#endif + + // Stop & signal interrupts on IOP + HW_DMA9_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + sif0.sifData.data = 0; + } + else if(FIFO_SIF1_W-sif0.fifoSize >= 2) // Chain mode + { + // Process DMA tag at HW_DMA9_TADR + sif0.sifData = *(struct sifData *)PSXM(HW_DMA9_TADR); + + sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4. + + SIF0write((u32*)PSXM(HW_DMA9_TADR+8), 4); + + //psxCycles += 2; + + HW_DMA9_MADR = sif0.sifData.data & 0xFFFFFF; + HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2; + //HW_DMA9_BCR = (sif0.sifData.words << 16) | 1; + sif0.counter = sif0.sifData.words & 0xFFFFFF; + notDone = 1; + +#ifdef SIF_LOG + SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)\n", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.sifData.words, sif0.sifData.data); +#endif + if(sif0.sifData.data & 0x40000000) + { +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + } + else + { +#ifdef SIF_LOG + SIF_LOG(" CNT %08X, %08X\n", sif0.sifData.data, sif0.sifData.words); +#endif + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int wTransfer = sif0.counter; // HW_DMA9_BCR >> 16; + + if (wTransfer > (FIFO_SIF0_W-sif0.fifoSize)) + wTransfer = (FIFO_SIF0_W-sif0.fifoSize); + +#ifdef SIF_LOG + SIF_LOG("+++++++++++ %lX of %lX\n", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/ ); +#endif + + SIF0write((u32*)PSXM(HW_DMA9_MADR), wTransfer); + HW_DMA9_MADR += wTransfer << 2; + //HW_DMA9_BCR = (HW_DMA9_BCR & 0xFFFF) | (((HW_DMA9_BCR >> 16) - wTransfer)<<16); + //psxCycles += (wTransfer / 4) * BIAS; + sif0.counter -= wTransfer; + + notDone = 1; + } + } + + if(sif0dma->chcr & 0x100) // If EE SIF enabled and there's something to transfer + { + int size = sif0dma->qwc; + if ((psHu32(DMAC_CTRL) & 0x30) == 0x10) { // STS == fromSIF0 + SysPrintf("SIF0 stall control\n"); + } + if(size > 0) // If we're reading something continue to do so + { + if(sif0.fifoSize > 0) + { + int readSize = size; + + if(readSize > (sif0.fifoSize/4)) + readSize = (sif0.fifoSize/4); + + //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X\n", readSize, sif0dma->madr); +#ifdef SIF_LOG + SIF_LOG("----------- %lX of %lX\n", readSize << 2, size << 2 ); +#endif + + _dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5); + + SIF0read((u32*)ptag, readSize*4); + Cpu->Clear(sif0dma->madr, readSize*4); + + //cycles += readSize * BIAS; + sif0dma->qwc -= readSize; + sif0dma->madr += readSize << 4; + + notDone = 1; + } + } + else + { + if(sif0.chain && sif0dma->chcr & 0x80000000) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" EE SIF interrupt\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.end) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" EE SIF end\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.fifoSize >= 4) // Read a tag + { + __declspec(align(16)) static u32 tag[4]; + SIF0read((u32*)&tag[0], 4); // Tag + + sif0dma->qwc = (u16)tag[0]; + sif0dma->madr = tag[1]; + sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000); + +#ifdef SIF_LOG + SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)\n", sif0dma->madr, sif0dma->qwc, (tag[0]>>28)&3, (tag[0]>>31)&1, tag[1], tag[0]); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) != 0)psHu32(DMAC_STADR) = sif0dma->madr; + notDone = 1; + sif0.chain = 1; + if(tag[0] & 0x40000000) + sif0.end = 1; + + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +void SIF1Dma() +{ + int id; + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + + do + { + notDone = 0; + + if(sif1dma->chcr & 0x100) // If EE SIF1 is enabled + { + if ((psHu32(DMAC_CTRL) & 0xC0) == 0xC0) { // STS == fromSIF1 + SysPrintf("SIF1 stall control\n"); + } + + if(sif1dma->qwc == 0) // If there's no more to transfer + { + if ((sif1dma->chcr & 0xc) == 0 || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA + { + // Stop & signal interrupts on EE + sif1dma->chcr &= ~0x100; + hwDmacIrq(6); + sif1.chain = 0; + sif1.end = 0; + } + else // Chain mode + { + // Process DMA tag at sif1dma->tadr + notDone = 1; + _dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6); + sif1dma->chcr = ( sif1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); // Copy the tag + sif1dma->qwc = (u16)ptag[0]; + + if (sif1dma->chcr & 0x40) { + SysPrintf("SIF1 TTE\n"); + SIF1write(ptag+2, 2); + } + + sif1.chain = 1; + id = (ptag[0] >> 28) & 0x7; + + switch(id) + { + case 0: // refe +#ifdef SIF_LOG + SIF_LOG(" REFE %08X\n", ptag[1]); +#endif + sif1.end = 1; + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 1: // cnt +#ifdef SIF_LOG + SIF_LOG(" CNT\n"); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + case 2: // next +#ifdef SIF_LOG + SIF_LOG(" NEXT %08X\n", ptag[1]); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = ptag[1]; + break; + + case 3: // ref + case 4: // refs +#ifdef SIF_LOG + SIF_LOG(" REF %08X\n", ptag[1]); +#endif + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 7: // end +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + sif1.end = 1; + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + default: + SysPrintf("Bad addr1 source chain\n"); + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int qwTransfer = sif1dma->qwc; + u32 *data; + + notDone = 1; + + _dmaGetAddr(sif1dma, data, sif1dma->madr, 6); + + if(qwTransfer > (FIFO_SIF1_W-sif1.fifoSize)/4) // Copy part of sif1dma into FIFO + qwTransfer = (FIFO_SIF1_W-sif1.fifoSize)/4; + + SIF1write(data, qwTransfer << 2); + + sif1dma->madr += qwTransfer << 4; + //cycles += qwTransfer * BIAS; + sif1dma->qwc -= qwTransfer; + } + } + + if(HW_DMA10_CHCR & 0x01000000 ) // If IOP SIF enabled and there's something to transfer + { + int size = sif1.counter; + + if(size > 0) // If we're reading something continue to do so + { + if(sif1.fifoSize > 0) + { + int readSize = size; + + if(readSize > sif1.fifoSize) + readSize = sif1.fifoSize; + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF doing transfer %04X to %08X\n", readSize, HW_DMA10_MADR); +#endif + + SIF1read((u32*)PSXM(HW_DMA10_MADR), readSize); + psxCpu->Clear(HW_DMA10_MADR, readSize); + //psxCycles += readSize / 4; + sif1.counter = size-readSize; + HW_DMA10_MADR += readSize << 2; + notDone = 1; + } + } + + if(size <= 0 || sif1.fifoSize == 0) + { + if(sif1.tagMode & 0x80) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" IOP SIF interrupt\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.tagMode & 0x40) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" IOP SIF end\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.fifoSize >= 4) // Read a tag + { + struct sifData d; + + SIF1read((u32*)&d, 4); + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d\n", d.data & 0xffffff, d.words, (d.data>>28)&7, (d.data>>31)&1); +#endif + HW_DMA10_MADR = d.data & 0xffffff; + sif1.counter = d.words; + sif1.tagMode = (d.data >> 24) & 0xFF; + notDone = 1; + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +int sif0Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(9, 0x800); + return 0; + }*/ + + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int sif1Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(10, 0x800); + return 0; + }*/ + + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int EEsif0Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<5)) { + INT(5, 0x800); + return 0; + }*/ + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + + return 1; +} + +int EEsif1Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<6)) { + INT(6, 0x800); + return 0; + }*/ + hwDmacIrq(6); + + return 1; +} + +void dmaSIF0() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr); +#endif + + if (sif0.fifoReadPos != sif0.fifoWritePos) { + SysPrintf("warning, sif0.fifoReadPos != sif0.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x2000; + if(sif0dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + hwIntcIrq(INTC_SBUS); + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void dmaSIF1() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr); +#endif + + if (sif1.fifoReadPos != sif1.fifoWritePos) { + SysPrintf("warning, sif1.fifoReadPos != sif1.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x4000; + if(sif1dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void dmaSIF2() { + +#ifdef SIF_LOG + SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx\n", + sif2dma->chcr, sif2dma->madr, sif2dma->qwc); +#endif + + sif2dma->chcr&= ~0x100; + hwDmacIrq(7); + SysPrintf("*PCSX2*: dmaSIF2\n"); +} + + +int sifFreeze(gzFile f, int Mode) { + gzfreeze(&sif0, sizeof(sif0)); + gzfreeze(&sif1, sizeof(sif1)); + return 0; +} diff --git a/Sif.h b/Sif.h new file mode 100644 index 0000000000..e381605cc9 --- /dev/null +++ b/Sif.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIF_H__ +#define __SIF_H__ + +#include "Common.h" + +struct sifData{ + int data, + words, + count, + addr; +}; + +int eeSifTransfer; + +DMACh *sif0ch; +DMACh *sif1ch; +DMACh *sif2ch; + +int sifInit(); +void SIF0Dma(); +void SIF1Dma(); +void dmaSIF0(); +void dmaSIF1(); +void dmaSIF2(); +int EEsif1Interrupt(); +int EEsif0Interrupt(); +int EEsif2Interrupt(); +int sifFreeze(gzFile f, int Mode); + + +#endif /* __SIF_H__ */ diff --git a/Sifcmd.h b/Sifcmd.h new file mode 100644 index 0000000000..b953fede54 --- /dev/null +++ b/Sifcmd.h @@ -0,0 +1,193 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIFCMD_H__ +#define __SIFCMD_H__ + +/* from sifcmd.h */ + +#define SYSTEM_CMD 0x80000000 + +struct t_sif_cmd_header +{ + u32 size; + void *dest; + int command; + u32 unknown; +}; + +struct t_sif_dma_transfer +{ + void *src, + *dest; + int size; + int attr; +}; + +struct t_sif_handler +{ + void (*handler) ( void *a, void *b); + void *buff; +}; + +#define SYSTEM_CMD_CHANGE_SADDR 0x80000000 +#define SYSTEM_CMD_INIT_CMD 0x80000002 +struct t_sif_saddr{ + struct t_sif_cmd_header hdr; //+00 + void *newaddr; //+10 +}; //=14 + +#define SYSTEM_CMD_SET_SREG 0x80000001 +struct t_sif_sreg{ + struct t_sif_cmd_header hdr; //+00 + int index; //+10 + unsigned int value; //+14 +}; //=18 + +#define SYSTEM_CMD_RESET 0x80000003 +struct t_sif_reset{ + struct t_sif_cmd_header hdr; //+00 + int size, //+10 + flag; //+14 + char data[80]; //+18 +}; //=68 + +/* end of sifcmd.h */ + +/* from sifsrpc.h */ + +struct t_sif_rpc_rend +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_client_data *client; /* 7 */ + u32 command; /* 8 */ + struct t_rpc_server_data *server; /* 9 */ + void *buff, /* 10 */ + *buff2; /* 11 */ +}; + +struct t_sif_rpc_other_data +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_receive_data *receive; /* 07 */ + void *src; /* 08 */ + void *dest; /* 09 */ + int size; /* 10 */ +}; + +struct t_sif_rpc_bind +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ +}; + +struct t_sif_rpc_call +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ + int send_size; /* 09 */ + void *receive; /* 10 */ + int rec_size; /* 11 */ + int has_async_ef; /* 12 */ + struct t_rpc_server_data *server; /* 13 */ +}; + +struct t_rpc_server_data +{ + int command; /* 04 00 */ + + void * (*func)(u32, void *, int); /* 05 01 */ + void *buff; /* 06 02 */ + int size; /* 07 03 */ + + void * (*func2)(u32, void *, int); /* 08 04 */ + void *buff2; /* 09 05 */ + int size2; /* 10 06 */ + + struct t_rpc_client_data *client; /* 11 07 */ + void *pkt_addr; /* 12 08 */ + int rpc_number; /* 13 09 */ + + void *receive; /* 14 10 */ + int rec_size; /* 15 11 */ + int has_async_ef; /* 16 12 */ + int rec_id; /* 17 13 */ + + struct t_rpc_server_data *link; /* 18 14 */ + struct r_rpc_server_data *next; /* 19 15 */ + struct t_rpc_data_queue *queued_object; /* 20 16 */ +}; + + +struct t_rpc_header +{ + void *pkt_addr; /* 04 00 */ + u32 rpc_id; /* 05 01 */ + int sema_id; /* 06 02 */ + u32 mode; /* 07 03 */ +}; + + +struct t_rpc_client_data +{ + struct t_rpc_header hdr; + u32 command; /* 04 08 */ + void *buff, /* 05 09 */ + *buff2; /* 06 10 */ + void (*end_function) ( void *); /* 07 11 */ + void *end_param; /* 08 12*/ + struct t_rpc_server_data *server; /* 09 13 */ +}; + +struct t_rpc_receive_data +{ + struct t_rpc_header hdr; + void *src, /* 04 */ + *dest; /* 05 */ + int size; /* 06 */ +}; + +struct t_rpc_data_queue +{ + int thread_id, /* 00 */ + active; /* 01 */ + struct t_rpc_server_data *svdata_ref, /* 02 */ + *start, /* 03 */ + *end; /* 04 */ + struct t_rpc_data_queue *next; /* 05 */ +}; + +/* end of sifrpc.h */ + +#endif//__SIFCMD_H__ diff --git a/Sio.c b/Sio.c new file mode 100644 index 0000000000..2104bf9d82 --- /dev/null +++ b/Sio.c @@ -0,0 +1,566 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "PsxCommon.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +// *** FOR WORKS ON PADS AND MEMORY CARDS ***** + +const unsigned char buf1[] = {0x25, 0x46, 0x01, 0x31, 0x00, 0xA2, 0x11, 0x01, 0xE1};//{0x64, 0x23, 0x2, 0x43, 0x0, 0xa2, 0x11, 0x1, 0xb4}; +const unsigned char buf2[] = {0xC5, 0xBD, 0x66, 0x00, 0x59, 0x44, 0x01, 0x02, 0x00};//{0x6d, 0x21, 0x30, 0x0, 0x55, 0x19, 0x2, 0x2, 0x30}; +const unsigned char buf4[] = {0x02, 0x9A, 0x9E, 0x06, 0x6D, 0x3C, 0xF0, 0x7E, 0xDF};//{0xa3, 0x5d, 0x2f, 0xa2, 0xd8, 0x7c, 0x5b, 0x35, 0xb9}; +const unsigned char buff[] = {0xC2, 0x39, 0x6F, 0x27, 0xC8, 0xDF, 0x2A, 0x23, 0xAD};//{0xf3, 0x9b, 0x32, 0x87, 0x31, 0xda, 0x9d, 0x10, 0xbb}; +const unsigned char buf11[] = {0xA8, 0x42, 0x5D, 0x87, 0x65, 0x32, 0x6F, 0xE8, 0xE0};//{0x39, 0xd2, 0xb9, 0x5c, 0xcf, 0x31, 0x2d, 0x23, 0xfe}; +const unsigned char buf13[] = {0x46, 0x31, 0xFC, 0x97, 0xA8, 0x6D, 0xE2, 0x12, 0x29};//{0x20, 0x2e, 0xd7, 0x99, 0x92, 0x29, 0x4a, 0x12, 0xa3}; + +const unsigned char cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; +struct mc_command_0x26_tag mc_command_0x26= + {'+', 512, 16, 0x4000, 0x52, 'Z'};//sizeof()==11 + +// clk cycle byte +// 4us * 8bits = ((PSXCLK / 1000000) * 32) / BIAS; (linuzappz) +#define SIO_INT() PSX_INT(16, PSXCLK/250000); /*270;*/ + +void _ReadMcd(char *data, u32 adr, int size) { + ReadMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +void _SaveMcd(char *data, u32 adr, int size) { + SaveMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +unsigned char xor(unsigned char *buf, unsigned int length){ + register unsigned char i, x; + + for (x=0, i=0; i>13)+1, value); +#endif + } + sio.mc_command=value; + if (sio.mc_command!=0x21 && sio.mc_command!=0x22 && sio.mc_command!=0x23 && + (sio.mc_command!=0xF0) && (sio.mc_command!=0xF1) && (sio.mc_command!=0xF2)) { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + } + return; + case 99://as is... + sio.packetsize++; + sio.parp++; + switch(sio.mc_command) + { + case 0x21: + case 0x22: + case 0x23: + if (sio.parp==2)sio.sector|=(value & 0xFF)<< 0; + if (sio.parp==3)sio.sector|=(value & 0xFF)<< 8; + if (sio.parp==4)sio.sector|=(value & 0xFF)<<16; + if (sio.parp==5)sio.sector|=(value & 0xFF)<<24; + if (sio.parp==6) + { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X sio.sector 0x%04X\n", + ((sio.CtrlReg&0x2000)>>13)+1, sio.mc_command, sio.sector); +#endif + } + break; + case 0x27: + if(sio.parp==2) { + sio.terminator = value; + sio.buf[4] = value; + } + break; + case 0x28: + if(sio.parp == 2) { + sio.buf[2] = '+'; + if(value == 0) { + sio.buf[4] = 0xFF; + sio.buf[3] = sio.terminator; + }else{ + sio.buf[4] = 0x5A; + sio.buf[3] = sio.terminator; + } + } + break; + case 0x42: + if (sio.parp==2) { + sio.bufcount=5+value; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + sio.buf[sio.bufcount]=sio.terminator; + } else + if ((sio.parp>2) && (sio.parp>13)+1, value, xor(&sio.buf[3], sio.bufcount-5)); +#endif + } + } + break; + case 0x43: + if (sio.parp==2){ + sio.bufcount=value+5; + sio.buf[3]='+'; + _ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value); + if(sio.mode==2) { + int j; + for(j=0; j < value; j++) + sio.buf[4+j] = ~sio.buf[4+j]; + } + sio.k+=value; + sio.buf[sio.bufcount-1]=xor(&sio.buf[4], value); + sio.buf[sio.bufcount]=sio.terminator; + } + break; + case 0x82: + if(sio.parp==2) { + sio.buf[2]='+'; + sio.buf[3]=sio.terminator; + } + break; + case 0xF0: + if (sio.parp==2) + { + u32 flag=0; +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0xF0:0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + switch(value){ + case 1: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf1,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 2: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf2,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 4: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf4,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 6: + case 7: + case 11: + flag=0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + break;//IN + case 15: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buff,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 17: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf11,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 19: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf13,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + default: + sio.bufcount=4; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + } + + if ((sio.bufcount==13) && flag){ + sio.buf[sio.bufcount-1] = 0;//xor value for OUT data + sio.buf[3]='+'; + } + sio.buf[sio.bufcount]=sio.terminator; + } + break; + } + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + return; + } + + switch (sio.mtapst) { + case 0x1: + sio.packetsize++; + sio.parp = 1; + SIO_INT(); + switch(value) { + case 0x12: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x13: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x21: sio.mtapst = 2; sio.bufcount = 6; break; + } + sio.buf[sio.bufcount]='Z'; + sio.buf[sio.bufcount-1]='+'; + return; + case 0x2: + sio.packetsize++; + sio.parp++; + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + SIO_INT(); + return; + } + + switch (value) { + case 0x01: // start pad + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + + switch (sio.CtrlReg&0x2002) { + case 0x0002: sio.buf[0] = PAD1startPoll(1); break; + case 0x2002: sio.buf[0] = PAD2startPoll(2); break; + } + + sio.bufcount = 2; + sio.parp = 0; + sio.padst = 1; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x21: // start mtap + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio.mtapst = 1; + sio2.packet.recvVal1 = 0x1D100; // Mtap is not connected :) + SIO_INT(); + return; + + case 0x61: // start remote control sensor + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x81: // start memcard + sio.StatReg &= ~TX_EMPTY; + sio.StatReg |= RX_RDY; + memcpy(sio.buf, cardh, 4); + sio.parp = 0; + sio.bufcount = 3; + sio.mcdst = 1; + sio.packetsize = 1; + sio.rdwr = 0; + sio2.packet.recvVal1 = 0x1100; // Memcard1 is present + SIO_INT(); + return; + } +} + +void sioWriteCtrl16(unsigned short value) { + sio.CtrlReg = value & ~RESET_ERR; + if (value & RESET_ERR) sio.StatReg &= ~IRQ; + if ((sio.CtrlReg & SIO_RESET) || (!sio.CtrlReg)) { + sio.mtapst = 0; sio.padst = 0; sio.mcdst = 0; sio.parp = 0; + sio.StatReg = TX_RDY | TX_EMPTY; + psxRegs.interrupt&= ~(1<<16); + } +} + +int sioInterrupt() { +#ifdef PAD_LOG + PAD_LOG("Sio Interrupt\n"); +#endif + sio.StatReg|= IRQ; + psxHu32(0x1070)|=0x80; + return 1; +} + +FILE *LoadMcd(int mcd) { + char str[256]; + FILE *f; + + if (mcd == 1) { + strcpy(str, Config.Mcd1); + } else { + strcpy(str, Config.Mcd2); + } + if (*str == 0) sprintf(str, "memcards/Mcd00%d.ps2", mcd); + f = fopen(str, "r+b"); + if (f == NULL) { + CreateMcd(str); + f = fopen(str, "r+b"); + } + if (f == NULL) { + SysMessage (_("Failed loading MemCard %s"), str); return NULL; + } + + return f; +} + +void SeekMcd(FILE *f, u32 adr) { + u32 size; + + fseek(f, 0, SEEK_END); size = ftell(f); + if (size == MCD_SIZE + 64) + fseek(f, adr + 64, SEEK_SET); + else if (size == MCD_SIZE + 3904) + fseek(f, adr + 3904, SEEK_SET); + else + fseek(f, adr, SEEK_SET); +} + +void ReadMcd(int mcd, char *data, u32 adr, int size) { + FILE *f = LoadMcd(mcd); + if (f == NULL) { + memset(data, 0, size); + return; + } + SeekMcd(f, adr); + fread(data, 1, size, f); + fclose(f); +} + +void SaveMcd(int mcd, char *data, u32 adr, int size) { + FILE *f = LoadMcd(mcd); + if (f == NULL) { + return; + } + SeekMcd(f, adr); + fwrite(data, 1, size, f); + fclose(f); +} + +void CreateMcd(char *mcd) { + FILE *fp; + int i=0, j=0; + int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; + + fp = fopen(mcd, "wb"); + if (fp == NULL) return; + for(i=0; i < 16384; i++) + { + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 16; j++) fputc(enc[j],fp); + } + fclose(fp); +} + +int sioFreeze(gzFile f, int Mode) { + gzfreeze(&sio, sizeof(sio)); + + return 0; +} + + diff --git a/Sio.h b/Sio.h new file mode 100644 index 0000000000..816bfac04d --- /dev/null +++ b/Sio.h @@ -0,0 +1,114 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _SIO_H_ +#define _SIO_H_ + +typedef struct { + u16 StatReg; + u16 ModeReg; + u16 CtrlReg; + u16 BaudReg; + + u8 buf[256]; + u32 bufcount; + u32 parp; + u32 mcdst,rdwr; + u8 adrH,adrL; + u32 padst; + u32 mtapst; + u32 packetsize; + + u8 terminator; + u8 mode; + u8 mc_command; + u32 lastsector; + u32 sector; + u32 k; +} _sio; +_sio sio; + +#define MCD_SIZE (1024 * 8 * 16) +#define MC2_SIZE (1024 * 528 * 16) + +// Status Flags +#define TX_RDY 0x0001 +#define RX_RDY 0x0002 +#define TX_EMPTY 0x0004 +#define PARITY_ERR 0x0008 +#define RX_OVERRUN 0x0010 +#define FRAMING_ERR 0x0020 +#define SYNC_DETECT 0x0040 +#define DSR 0x0080 +#define CTS 0x0100 +#define IRQ 0x0200 + +// Control Flags +#define TX_PERM 0x0001 +#define DTR 0x0002 +#define RX_PERM 0x0004 +#define BREAK 0x0008 +#define RESET_ERR 0x0010 +#define RTS 0x0020 +#define SIO_RESET 0x0040 + +int Mcd1Size, Mcd2Size; + +int sioInit(); +void sioShutdown(); +unsigned char sioRead8(); +void sioWrite8(unsigned char value); +void sioWriteCtrl16(unsigned short value); +int sioInterrupt(); +int sioFreeze(gzFile f, int Mode); + +FILE *LoadMcd(int mcd); +void ReadMcd(int mcd, char *data, u32 adr, int size); +void SaveMcd(int mcd, char *data, u32 adr, int size); +void CreateMcd(char *mcd); + +typedef struct { + char Title[48]; + char ID[14]; + char Name[16]; + int IconCount; + short Icon[16*16*3]; + unsigned char Flags; +} McdBlock; + +#ifdef __WIN32__ +#pragma pack(1) +#endif +struct mc_command_0x26_tag{ + u8 field_151; //+02 flags + u16 sectorSize; //+03 divide to it + u16 field_2C; //+05 divide to it + u32 mc_size; //+07 + u8 xor; //+0b don't forget to recalculate it!!! + u8 Z; //+0c +#ifdef __WIN32__ +}; +#pragma pack() +#else +} __attribute__((packed)); +#endif + +void GetMcdBlockInfo(int mcd, int block, McdBlock *info); + +#endif diff --git a/Stats.c b/Stats.c new file mode 100644 index 0000000000..1b3d4395aa --- /dev/null +++ b/Stats.c @@ -0,0 +1,70 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "PsxCommon.h" + +void statsOpen() { + stats.vsyncCount = 0; + stats.vsyncTime = time(NULL); + stats.eeCycles = 0; + stats.eeSCycle = 0; + stats.iopCycles = 0; + stats.iopSCycle = 0; +} + +void statsClose() { + time_t t; + FILE *f; + + t = time(NULL) - stats.vsyncTime; +#ifdef __WIN32__ + f = fopen("logs\\stats.txt", "w"); +#else + f = fopen("logs/stats.txt", "w"); +#endif + if (!f) { SysPrintf("Can't open stats.txt\n"); return; } + fprintf(f, "-- PCSX2 v%s statics--\n\n", PCSX2_VERSION); + fprintf(f, "Ran for %d seconds\n", t); + fprintf(f, "Total VSyncs: %d (%s)\n", stats.vsyncCount, Config.PsxType ? "PAL" : "NTSC"); +#ifndef __x86_64__ + fprintf(f, "VSyncs per Seconds: %g\n", (double)stats.vsyncCount / t); +#endif + fprintf(f, "Total EE Instructions Executed: %lld\n", stats.eeCycles); + fprintf(f, "Total IOP Instructions Executed: %lld\n", stats.iopCycles); + if (!CHECK_EEREC) fprintf(f, "Interpreter Mode\n"); + else fprintf(f, "Recompiler Mode: VUrec1 %s, VUrec0 %s\n", + CHECK_VU1REC ? "Enabled" : "Disabled", CHECK_VU0REC ? "Enabled" : "Disabled"); + fclose(f); +} + +void statsVSync() { + static u64 accum = 0, accumvu1 = 0; + static u32 frame = 0; + + stats.eeCycles+= cpuRegs.cycle - stats.eeSCycle; + stats.eeSCycle = cpuRegs.cycle; + stats.iopCycles+= psxRegs.cycle - stats.iopSCycle; + stats.iopSCycle = psxRegs.cycle; + stats.vsyncCount++; + stats.vif1count = 0; + stats.vu1count = 0; +} diff --git a/Stats.h b/Stats.h new file mode 100644 index 0000000000..a914e6b737 --- /dev/null +++ b/Stats.h @@ -0,0 +1,43 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __STATS_H__ +#define __STATS_H__ + +#include + +typedef struct { + time_t vsyncTime; + u32 vsyncCount; + u32 eeCycles; + u32 eeSCycle; + u32 iopCycles; + u32 iopSCycle; + + u32 ticko; + u32 framecount; + u32 vu1count; + u32 vif1count; +} Stats; +Stats stats; + +void statsOpen(); +void statsClose(); +void statsVSync(); + +#endif /* __STATS_H__ */ diff --git a/System.h b/System.h new file mode 100644 index 0000000000..a425b93c34 --- /dev/null +++ b/System.h @@ -0,0 +1,59 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +int SysInit(); // Init mem and plugins +void SysReset(); // Resets mem +void SysPrintf(char *fmt, ...); // Printf used by bios syscalls +void SysMessage(char *fmt, ...); // Message used to print msg to users +void SysUpdate(); // Called on VBlank (to update i.e. pads) +void SysRunGui(); // Returns to the Gui +void SysClose(); // Close mem and plugins +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void *SysMmap(uptr base, u32 size); +void SysMunmap(uptr base, u32 size); + +#ifdef WIN32_VIRTUAL_MEM +typedef struct _PSMEMORYBLOCK +{ + ULONG_PTR NumberPages; + ULONG_PTR* aPFNs; + ULONG_PTR* aVFNs; // virtual pages that own the physical pages +} PSMEMORYBLOCK; + +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock); +void SysPhysicalFree(PSMEMORYBLOCK* pblock); +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualFree(void* lpMemReserved, u32 size); + +void SysVirtualProtectAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualProtectFree(void* lpMemReserved, u32 size); + +BOOL SysMapUserPhysicalPages(PVOID Addr, ULONG_PTR NumPages, PULONG_PTR PageArray); + +// call to enable physical page allocation +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable); + +#endif + +#endif /* __SYSTEM_H__ */ diff --git a/VU.h b/VU.h new file mode 100644 index 0000000000..572222a667 --- /dev/null +++ b/VU.h @@ -0,0 +1,174 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU_H__ +#define __VU_H__ + +#define REG_STATUS_FLAG 16 +#define REG_MAC_FLAG 17 +#define REG_CLIP_FLAG 18 +#define REG_ACC_FLAG 19 // dummy flag that indicates that VFACC is written/read (nothing to do with VI[19]) +#define REG_R 20 +#define REG_I 21 +#define REG_Q 22 +#define REG_P 23 //only exists in micromode +#define REG_VF0_FLAG 24 // dummy flag that indicates VF0 is read (nothing to do with VI[24]) +#define REG_TPC 26 +#define REG_CMSAR0 27 +#define REG_FBRST 28 +#define REG_VPU_STAT 29 +#define REG_CMSAR1 31 + +enum VUStatus { + VU_Ready = 0, + VU_Run = 1, + VU_Stop = 2, +}; + +typedef union { + struct { + float x,y,z,w; + } f; + struct { + u32 x,y,z,w; + } i; + + float F[4]; + + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} VECTOR; + +typedef union { + float F; + s32 SL; + u32 UL; + s16 SS[2]; + u16 US[2]; + s8 SC[4]; + u8 UC[4]; +} REG_VI; + +#define VUFLAG_BREAKONMFLAG 0x00000001 +#define VUFLAG_MFLAGSET 0x00000002 + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; + u32 statusflag; +} fdivPipe; + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; +} efuPipe; + +typedef struct { + int enable; + int reg; + int xyzw; + u32 sCycle; + u32 Cycle; + u32 macflag; + u32 statusflag; + u32 clipflag; +} fmacPipe; + +typedef struct { + VECTOR VF[32]; + REG_VI VI[32]; + VECTOR ACC; + REG_VI q; + REG_VI p; + + u32 macflag; + u32 statusflag; + u32 clipflag; + + u32 cycle; + u32 flags; + + void (*vuExec)(void*); + VIFregisters *vifRegs; + + u8 *Mem; + u8 *Micro; + + u32 code; + u32 maxmem; + u32 maxmicro; + + u16 branch; + u16 ebit; + u32 branchpc; + + fmacPipe fmac[8]; + fdivPipe fdiv; + efuPipe efu; + +} VURegs; + +#define VUPIPE_NONE 0 +#define VUPIPE_FMAC 1 +#define VUPIPE_FDIV 2 +#define VUPIPE_EFU 3 +#define VUPIPE_IALU 4 +#define VUPIPE_BRANCH 5 +#define VUPIPE_XGKICK 6 + +#define VUREG_READ 0x1 +#define VUREG_WRITE 0x2 + +typedef struct { + u8 pipe; // if 0xff, COP2 + u8 VFwrite; + u8 VFwxyzw; + u8 VFr0xyzw; + u8 VFr1xyzw; + u8 VFread0; + u8 VFread1; + u32 VIwrite; + u32 VIread; + int cycles; +} _VURegsNum; + +extern VURegs* g_pVU1; +extern VURegs VU0; + +#define VU1 (*g_pVU1) + +__forceinline u32* GET_VU_MEM(VURegs* VU, u32 addr) +{ + if( VU == g_pVU1 ) return (u32*)(VU1.Mem+(addr&0x3fff)); + + if( addr >= 0x4200 ) return &VU1.VI[(addr>>2)&0x1f].UL; + + return (u32*)(VU0.Mem+(addr&0x0fff)); +} + +#endif /* __VU_H__ */ diff --git a/VU0.c b/VU0.c new file mode 100644 index 0000000000..4e86c33be0 --- /dev/null +++ b/VU0.c @@ -0,0 +1,383 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO + -Fix the flags Proper as they aren't handle now.. + -Add BC Table opcodes + -Add Interlock in QMFC2,QMTC2,CFC2,CTC2 + -Finish instruction set + -Bug Fixes!!! +*/ + +#include +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUops.h" +#include "VUmicro.h" + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X (cpuRegs.code>>24) & 0x1 +#define _Y (cpuRegs.code>>23) & 0x1 +#define _Z (cpuRegs.code>>22) & 0x1 +#define _W (cpuRegs.code>>21) & 0x1 + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) + +#include "VUflags.h" + +__declspec(align(16)) VURegs VU0; + +void COP2() { +#ifdef VU0_LOG + VU0_LOG("%s\n", disR5900Fasm(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP2PrintTable[_Rs_](); +} + +void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();} +void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();} + +void COP2_SPECIAL2() { + Int_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](); +} + +void COP2_Unknown() +{ +#ifdef CPU_LOG + CPU_LOG("Unknown COP2 opcode called\n"); +#endif +} + +void LQC2() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)cpuRegs.code; + if (_Ft_) { + memRead128(addr, &VU0.VF[_Ft_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +// Asadr.Changed +void SQC2() { + u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0]; + memWrite64(addr, VU0.VF[_Ft_].UD[0]); + memWrite64(addr+8,VU0.VF[_Ft_].UD[1]); +} + + +//**************************************************************************** +void _vu0WaitMicro() { + int startcycle; + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) { + return; + } + + startcycle = VU0.cycle; + + VU0.flags|= VUFLAG_BREAKONMFLAG; + VU0.flags&= ~VUFLAG_MFLAGSET; + + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU0Block(); + } while ((VU0.VI[REG_VPU_STAT].UL & 0x1) && (VU0.flags & VUFLAG_MFLAGSET) == 0); + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + + //NEW + cpuRegs.cycle += (VU0.cycle-startcycle)*2; + VU0.flags&= ~VUFLAG_BREAKONMFLAG; +} + + +void QMFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UD[0] = VU0.VF[_Fs_].UD[0]; + cpuRegs.GPR.r[_Rt_].UD[1] = VU0.VF[_Fs_].UD[1]; +} + +void QMTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + VU0.VF[_Fs_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + VU0.VF[_Fs_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void CFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UL[0] = VU0.VI[_Fs_].UL; + if(VU0.VI[_Fs_].UL & 0x80000000) + cpuRegs.GPR.r[_Rt_].UL[1] = 0xffffffff; + else + cpuRegs.GPR.r[_Rt_].UL[1] = 0; +} + +void CTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + VU0.VI[REG_FBRST].UL = cpuRegs.GPR.r[_Rt_].UL[0] & 0x0C0C; + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x1) { // VU0 Force Break + SysPrintf("fixme: VU0 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x2) { // VU0 Reset + //SysPrintf("fixme: VU0 Reset\n"); + vu0ResetRegs(); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x100) { // VU1 Force Break + SysPrintf("fixme: VU1 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x200) { // VU1 Reset +// SysPrintf("fixme: VU1 Reset\n"); + vu1ResetRegs(); + } + break; + case REG_CMSAR1: // REG_CMSAR1 + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100) ) { + VU1.VI[REG_TPC].UL = cpuRegs.GPR.r[_Rt_].US[0]; + vu1ExecMicro(VU1.VI[REG_TPC].UL); // Execute VU1 Micro SubRoutine + } + break; + default: + VU0.VI[_Fs_].UL = cpuRegs.GPR.r[_Rt_].UL[0]; + break; + } +} + +//--------------------------------------------------------------------------------------- + + +#define SYNCMSFLAGS() VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; VU0.VI[REG_MAC_FLAG].UL = VU0.macflag; +#define SYNCFDIV() VU0.VI[REG_Q].UL = VU0.q.UL; VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; + +void VABS() { VU0.code = cpuRegs.code; _vuABS(&VU0); } +void VADD() { VU0.code = cpuRegs.code; _vuADD(&VU0); SYNCMSFLAGS(); } +void VADDi() { VU0.code = cpuRegs.code; _vuADDi(&VU0); SYNCMSFLAGS(); } +void VADDq() { VU0.code = cpuRegs.code; _vuADDq(&VU0); SYNCMSFLAGS(); } +void VADDx() { VU0.code = cpuRegs.code; _vuADDx(&VU0); SYNCMSFLAGS(); } +void VADDy() { VU0.code = cpuRegs.code; _vuADDy(&VU0); SYNCMSFLAGS(); } +void VADDz() { VU0.code = cpuRegs.code; _vuADDz(&VU0); SYNCMSFLAGS(); } +void VADDw() { VU0.code = cpuRegs.code; _vuADDw(&VU0); SYNCMSFLAGS(); } +void VADDA() { VU0.code = cpuRegs.code; _vuADDA(&VU0); SYNCMSFLAGS(); } +void VADDAi() { VU0.code = cpuRegs.code; _vuADDAi(&VU0); SYNCMSFLAGS(); } +void VADDAq() { VU0.code = cpuRegs.code; _vuADDAq(&VU0); SYNCMSFLAGS(); } +void VADDAx() { VU0.code = cpuRegs.code; _vuADDAx(&VU0); SYNCMSFLAGS(); } +void VADDAy() { VU0.code = cpuRegs.code; _vuADDAy(&VU0); SYNCMSFLAGS(); } +void VADDAz() { VU0.code = cpuRegs.code; _vuADDAz(&VU0); SYNCMSFLAGS(); } +void VADDAw() { VU0.code = cpuRegs.code; _vuADDAw(&VU0); SYNCMSFLAGS(); } +void VSUB() { VU0.code = cpuRegs.code; _vuSUB(&VU0); SYNCMSFLAGS(); } +void VSUBi() { VU0.code = cpuRegs.code; _vuSUBi(&VU0); SYNCMSFLAGS(); } +void VSUBq() { VU0.code = cpuRegs.code; _vuSUBq(&VU0); SYNCMSFLAGS(); } +void VSUBx() { VU0.code = cpuRegs.code; _vuSUBx(&VU0); SYNCMSFLAGS(); } +void VSUBy() { VU0.code = cpuRegs.code; _vuSUBy(&VU0); SYNCMSFLAGS(); } +void VSUBz() { VU0.code = cpuRegs.code; _vuSUBz(&VU0); SYNCMSFLAGS(); } +void VSUBw() { VU0.code = cpuRegs.code; _vuSUBw(&VU0); SYNCMSFLAGS(); } +void VSUBA() { VU0.code = cpuRegs.code; _vuSUBA(&VU0); SYNCMSFLAGS(); } +void VSUBAi() { VU0.code = cpuRegs.code; _vuSUBAi(&VU0); SYNCMSFLAGS(); } +void VSUBAq() { VU0.code = cpuRegs.code; _vuSUBAq(&VU0); SYNCMSFLAGS(); } +void VSUBAx() { VU0.code = cpuRegs.code; _vuSUBAx(&VU0); SYNCMSFLAGS(); } +void VSUBAy() { VU0.code = cpuRegs.code; _vuSUBAy(&VU0); SYNCMSFLAGS(); } +void VSUBAz() { VU0.code = cpuRegs.code; _vuSUBAz(&VU0); SYNCMSFLAGS(); } +void VSUBAw() { VU0.code = cpuRegs.code; _vuSUBAw(&VU0); SYNCMSFLAGS(); } +void VMUL() { VU0.code = cpuRegs.code; _vuMUL(&VU0); SYNCMSFLAGS(); } +void VMULi() { VU0.code = cpuRegs.code; _vuMULi(&VU0); SYNCMSFLAGS(); } +void VMULq() { VU0.code = cpuRegs.code; _vuMULq(&VU0); SYNCMSFLAGS(); } +void VMULx() { VU0.code = cpuRegs.code; _vuMULx(&VU0); SYNCMSFLAGS(); } +void VMULy() { VU0.code = cpuRegs.code; _vuMULy(&VU0); SYNCMSFLAGS(); } +void VMULz() { VU0.code = cpuRegs.code; _vuMULz(&VU0); SYNCMSFLAGS(); } +void VMULw() { VU0.code = cpuRegs.code; _vuMULw(&VU0); SYNCMSFLAGS(); } +void VMULA() { VU0.code = cpuRegs.code; _vuMULA(&VU0); SYNCMSFLAGS(); } +void VMULAi() { VU0.code = cpuRegs.code; _vuMULAi(&VU0); SYNCMSFLAGS(); } +void VMULAq() { VU0.code = cpuRegs.code; _vuMULAq(&VU0); SYNCMSFLAGS(); } +void VMULAx() { VU0.code = cpuRegs.code; _vuMULAx(&VU0); SYNCMSFLAGS(); } +void VMULAy() { VU0.code = cpuRegs.code; _vuMULAy(&VU0); SYNCMSFLAGS(); } +void VMULAz() { VU0.code = cpuRegs.code; _vuMULAz(&VU0); SYNCMSFLAGS(); } +void VMULAw() { VU0.code = cpuRegs.code; _vuMULAw(&VU0); SYNCMSFLAGS(); } +void VMADD() { VU0.code = cpuRegs.code; _vuMADD(&VU0); SYNCMSFLAGS(); } +void VMADDi() { VU0.code = cpuRegs.code; _vuMADDi(&VU0); SYNCMSFLAGS(); } +void VMADDq() { VU0.code = cpuRegs.code; _vuMADDq(&VU0); SYNCMSFLAGS(); } +void VMADDx() { VU0.code = cpuRegs.code; _vuMADDx(&VU0); SYNCMSFLAGS(); } +void VMADDy() { VU0.code = cpuRegs.code; _vuMADDy(&VU0); SYNCMSFLAGS(); } +void VMADDz() { VU0.code = cpuRegs.code; _vuMADDz(&VU0); SYNCMSFLAGS(); } +void VMADDw() { VU0.code = cpuRegs.code; _vuMADDw(&VU0); SYNCMSFLAGS(); } +void VMADDA() { VU0.code = cpuRegs.code; _vuMADDA(&VU0); SYNCMSFLAGS(); } +void VMADDAi() { VU0.code = cpuRegs.code; _vuMADDAi(&VU0); SYNCMSFLAGS(); } +void VMADDAq() { VU0.code = cpuRegs.code; _vuMADDAq(&VU0); SYNCMSFLAGS(); } +void VMADDAx() { VU0.code = cpuRegs.code; _vuMADDAx(&VU0); SYNCMSFLAGS(); } +void VMADDAy() { VU0.code = cpuRegs.code; _vuMADDAy(&VU0); SYNCMSFLAGS(); } +void VMADDAz() { VU0.code = cpuRegs.code; _vuMADDAz(&VU0); SYNCMSFLAGS(); } +void VMADDAw() { VU0.code = cpuRegs.code; _vuMADDAw(&VU0); SYNCMSFLAGS(); } +void VMSUB() { VU0.code = cpuRegs.code; _vuMSUB(&VU0); SYNCMSFLAGS(); } +void VMSUBi() { VU0.code = cpuRegs.code; _vuMSUBi(&VU0); SYNCMSFLAGS(); } +void VMSUBq() { VU0.code = cpuRegs.code; _vuMSUBq(&VU0); SYNCMSFLAGS(); } +void VMSUBx() { VU0.code = cpuRegs.code; _vuMSUBx(&VU0); SYNCMSFLAGS(); } +void VMSUBy() { VU0.code = cpuRegs.code; _vuMSUBy(&VU0); SYNCMSFLAGS(); } +void VMSUBz() { VU0.code = cpuRegs.code; _vuMSUBz(&VU0); SYNCMSFLAGS(); } +void VMSUBw() { VU0.code = cpuRegs.code; _vuMSUBw(&VU0); SYNCMSFLAGS(); } +void VMSUBA() { VU0.code = cpuRegs.code; _vuMSUBA(&VU0); SYNCMSFLAGS(); } +void VMSUBAi() { VU0.code = cpuRegs.code; _vuMSUBAi(&VU0); SYNCMSFLAGS(); } +void VMSUBAq() { VU0.code = cpuRegs.code; _vuMSUBAq(&VU0); SYNCMSFLAGS(); } +void VMSUBAx() { VU0.code = cpuRegs.code; _vuMSUBAx(&VU0); SYNCMSFLAGS(); } +void VMSUBAy() { VU0.code = cpuRegs.code; _vuMSUBAy(&VU0); SYNCMSFLAGS(); } +void VMSUBAz() { VU0.code = cpuRegs.code; _vuMSUBAz(&VU0); SYNCMSFLAGS(); } +void VMSUBAw() { VU0.code = cpuRegs.code; _vuMSUBAw(&VU0); SYNCMSFLAGS(); } +void VMAX() { VU0.code = cpuRegs.code; _vuMAX(&VU0); } +void VMAXi() { VU0.code = cpuRegs.code; _vuMAXi(&VU0); } +void VMAXx() { VU0.code = cpuRegs.code; _vuMAXx(&VU0); } +void VMAXy() { VU0.code = cpuRegs.code; _vuMAXy(&VU0); } +void VMAXz() { VU0.code = cpuRegs.code; _vuMAXz(&VU0); } +void VMAXw() { VU0.code = cpuRegs.code; _vuMAXw(&VU0); } +void VMINI() { VU0.code = cpuRegs.code; _vuMINI(&VU0); } +void VMINIi() { VU0.code = cpuRegs.code; _vuMINIi(&VU0); } +void VMINIx() { VU0.code = cpuRegs.code; _vuMINIx(&VU0); } +void VMINIy() { VU0.code = cpuRegs.code; _vuMINIy(&VU0); } +void VMINIz() { VU0.code = cpuRegs.code; _vuMINIz(&VU0); } +void VMINIw() { VU0.code = cpuRegs.code; _vuMINIw(&VU0); } +void VOPMULA() { VU0.code = cpuRegs.code; _vuOPMULA(&VU0); SYNCMSFLAGS(); } +void VOPMSUB() { VU0.code = cpuRegs.code; _vuOPMSUB(&VU0); SYNCMSFLAGS(); } +void VNOP() { VU0.code = cpuRegs.code; _vuNOP(&VU0); } +void VFTOI0() { VU0.code = cpuRegs.code; _vuFTOI0(&VU0); } +void VFTOI4() { VU0.code = cpuRegs.code; _vuFTOI4(&VU0); } +void VFTOI12() { VU0.code = cpuRegs.code; _vuFTOI12(&VU0); } +void VFTOI15() { VU0.code = cpuRegs.code; _vuFTOI15(&VU0); } +void VITOF0() { VU0.code = cpuRegs.code; _vuITOF0(&VU0); } +void VITOF4() { VU0.code = cpuRegs.code; _vuITOF4(&VU0); } +void VITOF12() { VU0.code = cpuRegs.code; _vuITOF12(&VU0); } +void VITOF15() { VU0.code = cpuRegs.code; _vuITOF15(&VU0); } +void VCLIPw() { VU0.code = cpuRegs.code; _vuCLIP(&VU0); VU0.VI[REG_CLIP_FLAG].UL = VU0.clipflag; } + +void VDIV() { VU0.code = cpuRegs.code; _vuDIV(&VU0); SYNCFDIV(); } +void VSQRT() { VU0.code = cpuRegs.code; _vuSQRT(&VU0); SYNCFDIV(); } +void VRSQRT() { VU0.code = cpuRegs.code; _vuRSQRT(&VU0); SYNCFDIV(); } +void VIADD() { VU0.code = cpuRegs.code; _vuIADD(&VU0); } +void VIADDI() { VU0.code = cpuRegs.code; _vuIADDI(&VU0); } +void VIADDIU() { VU0.code = cpuRegs.code; _vuIADDIU(&VU0); } +void VIAND() { VU0.code = cpuRegs.code; _vuIAND(&VU0); } +void VIOR() { VU0.code = cpuRegs.code; _vuIOR(&VU0); } +void VISUB() { VU0.code = cpuRegs.code; _vuISUB(&VU0); } +void VISUBIU() { VU0.code = cpuRegs.code; _vuISUBIU(&VU0); } +void VMOVE() { VU0.code = cpuRegs.code; _vuMOVE(&VU0); } +void VMFIR() { VU0.code = cpuRegs.code; _vuMFIR(&VU0); } +void VMTIR() { VU0.code = cpuRegs.code; _vuMTIR(&VU0); } +void VMR32() { VU0.code = cpuRegs.code; _vuMR32(&VU0); } +void VLQ() { VU0.code = cpuRegs.code; _vuLQ(&VU0); } +void VLQD() { VU0.code = cpuRegs.code; _vuLQD(&VU0); } +void VLQI() { VU0.code = cpuRegs.code; _vuLQI(&VU0); } +void VSQ() { VU0.code = cpuRegs.code; _vuSQ(&VU0); } +void VSQD() { VU0.code = cpuRegs.code; _vuSQD(&VU0); } +void VSQI() { VU0.code = cpuRegs.code; _vuSQI(&VU0); } +void VILW() { VU0.code = cpuRegs.code; _vuILW(&VU0); } +void VISW() { VU0.code = cpuRegs.code; _vuISW(&VU0); } +void VILWR() { VU0.code = cpuRegs.code; _vuILWR(&VU0); } +void VISWR() { VU0.code = cpuRegs.code; _vuISWR(&VU0); } +void VRINIT() { VU0.code = cpuRegs.code; _vuRINIT(&VU0); } +void VRGET() { VU0.code = cpuRegs.code; _vuRGET(&VU0); } +void VRNEXT() { VU0.code = cpuRegs.code; _vuRNEXT(&VU0); } +void VRXOR() { VU0.code = cpuRegs.code; _vuRXOR(&VU0); } +void VWAITQ() { VU0.code = cpuRegs.code; _vuWAITQ(&VU0); } +void VFSAND() { VU0.code = cpuRegs.code; _vuFSAND(&VU0); } +void VFSEQ() { VU0.code = cpuRegs.code; _vuFSEQ(&VU0); } +void VFSOR() { VU0.code = cpuRegs.code; _vuFSOR(&VU0); } +void VFSSET() { VU0.code = cpuRegs.code; _vuFSSET(&VU0); } +void VFMAND() { VU0.code = cpuRegs.code; _vuFMAND(&VU0); } +void VFMEQ() { VU0.code = cpuRegs.code; _vuFMEQ(&VU0); } +void VFMOR() { VU0.code = cpuRegs.code; _vuFMOR(&VU0); } +void VFCAND() { VU0.code = cpuRegs.code; _vuFCAND(&VU0); } +void VFCEQ() { VU0.code = cpuRegs.code; _vuFCEQ(&VU0); } +void VFCOR() { VU0.code = cpuRegs.code; _vuFCOR(&VU0); } +void VFCSET() { VU0.code = cpuRegs.code; _vuFCSET(&VU0); } +void VFCGET() { VU0.code = cpuRegs.code; _vuFCGET(&VU0); } +void VXITOP() { VU0.code = cpuRegs.code; _vuXITOP(&VU0); } + +#define CP2COND (/*(VU0.VI[REG_VPU_STAT].US[0] & 1) | */((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) + +#define BC2(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC2F() { BC2(== 0);} +void BC2T() { BC2(== 1);} + +#define BC2L(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC2FL() { BC2L(== 0);} +void BC2TL() { BC2L(== 1);} + +void vu0Finish() +{ + if( (VU0.VI[REG_VPU_STAT].UL & 0x1) ) { + int i = 0; + while(i++ < 32) { + Cpu->ExecuteVU0Block(); + if(!(VU0.VI[REG_VPU_STAT].UL & 0x1)) + break; + } + + if(VU0.VI[REG_VPU_STAT].UL & 0x1) { + VU0.VI[REG_VPU_STAT].UL &= ~1; +#ifdef PCSX2_DEVBUILD + SysPrintf("VU0 stall\n"); +#endif + } + } +} + +void VCALLMS() { + + vu0Finish(); + vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void VCALLMSR() { + vu0Finish(); + vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} diff --git a/VU0.h b/VU0.h new file mode 100644 index 0000000000..5a8bc6dd00 --- /dev/null +++ b/VU0.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU0_H__ +#define __VU0_H__ + +#include "VU.h" +#define Lcode cpuRegs.code + +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); + +void recResetVU0( void ); + +void vu0Finish(); + +extern VURegs VU0; + +extern char *recMemVU0; /* VU0 blocks */ +extern char *recVU0; /* VU1 mem */ +extern char *recVU0mac; +extern char *recVU0status; +extern char *recVU0clip; +extern char *recVU0Q; +extern char *recVU0cycles; +extern char* recVU0XMMRegs; +extern char *recPtrVU0; + +extern u32 vu0recpcold; + +#endif /* __VU0_H__ */ diff --git a/VU0micro.c b/VU0micro.c new file mode 100644 index 0000000000..6dcaa9be93 --- /dev/null +++ b/VU0micro.c @@ -0,0 +1,712 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4113) +#endif + +#ifdef WIN32_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +extern PSMEMORYMAP *memLUT; +#endif + +int vu0Init() +{ +#ifdef WIN32_VIRTUAL_MEM + // unmap all vu0 pages + SysMapUserPhysicalPages(PS2MEM_VU0MICRO, 16, NULL); + + // mirror 4 times + VU0.Micro = PS2MEM_VU0MICRO; + memLUT[0x11000].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11000].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11001].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11001].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11002].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11002].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11003].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11003].aVFNs = &s_psVuMem.aVFNs[0]; + + // since vuregisters are mapped in vumem0, go to diff addr, but mapping to same physical addr + VU0.Mem = VirtualAlloc((void*)0x11000000, 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( VU0.Mem != (void*)0x11000000 ) { + SysPrintf("Failed to alloc vu0mem 0x11000000 %d\n", GetLastError()); + return -1; + } + + memLUT[0x11004].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11004].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11005].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11005].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11006].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11006].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11007].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11007].aVFNs = &s_psVuMem.aVFNs[1]; + + // map only registers + SysMapUserPhysicalPages(VU0.Mem+0x4000, 1, &s_psVuMem.aPFNs[2]); +#else + VU0.Mem = (u8*)_aligned_malloc(0x4000+sizeof(VURegs), 16); // for VU1 + VU0.Micro = (u8*)_aligned_malloc(4*1024, 16); + memset(VU0.Mem, 0, 0x4000+sizeof(VURegs)); + memset(VU0.Micro, 0, 4*1024); +#endif + + +// VU0.VF = (VECTOR*)_aligned_malloc(32*sizeof(VECTOR), 16); +// VU0.VI = (REG_VI*)_aligned_malloc(32*sizeof(REG_VI), 16); +// if (VU0.VF == NULL || VU0.VI == NULL) { +// SysMessage(_("Error allocating memory")); return -1; +// } + + /* this is kinda tricky, maxmem is set to 0x4400 here, + tho it's not 100% accurate, since the mem goes from + 0x0000 - 0x1000 (Mem) and 0x4000 - 0x4400 (VU1 Regs), + i guess it shouldn't be a problem, + at least hope so :) (linuz) + */ + VU0.maxmem = 0x4400-4; + VU0.maxmicro = 4*1024-4; + VU0.vuExec = vu0Exec; + VU0.vifRegs = vif0Regs; + + if( CHECK_VU0REC ) { + SuperVUInit(0); + } + + vu0Reset(); + + return 0; +} + +void vu0Shutdown() +{ + if( CHECK_VU0REC ) { + SuperVUDestroy(0); + } + +#ifdef WIN32_VIRTUAL_MEM + if( !SysMapUserPhysicalPages(VU0.Mem, 16, NULL) ) + SysPrintf("err releasing vu0 mem %d\n", GetLastError()); + if( VirtualFree(VU0.Mem, 0, MEM_RELEASE) == 0 ) + SysPrintf("err freeing vu0 %d\n", GetLastError()); +#else + _aligned_free(VU0.Mem); + _aligned_free(VU0.Micro); +#endif + + VU0.Mem = NULL; + VU0.Micro = NULL; +// _aligned_free(VU0.VF); VU0.VF = NULL; +// _aligned_free(VU0.VI); VU0.VI = NULL; +} + +void vu0ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0 + VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0 + vif0Regs->stat &= ~4; +} + +void vu0Reset() +{ + memset(&VU0.ACC, 0, sizeof(VECTOR)); + memset(VU0.VF, 0, sizeof(VECTOR)*32); + memset(VU0.VI, 0, sizeof(REG_VI)*32); + VU0.VF[0].f.x = 0.0f; + VU0.VF[0].f.y = 0.0f; + VU0.VF[0].f.z = 0.0f; + VU0.VF[0].f.w = 1.0f; + VU0.VI[0].UL = 0; + memset(VU0.Mem, 0, 4*1024); + memset(VU0.Micro, 0, 4*1024); + + recResetVU0(); +} + +void recResetVU0( void ) +{ + if( CHECK_VU0REC ) { + SuperVUReset(0); + } +} + +void vu0Freeze(gzFile f, int Mode) { + gzfreeze(&VU0.ACC, sizeof(VECTOR)); + gzfreeze(&VU0.code, sizeof(u32)); + gzfreeze(VU0.Mem, 4*1024); + gzfreeze(VU0.Micro, 4*1024); + gzfreeze(VU0.VF, 32*sizeof(VECTOR)); + gzfreeze(VU0.VI, 32*sizeof(REG_VI)); +} + + +void VU0MI_XGKICK() { +} + +void VU0MI_XTOP() { +} + +void vu0ExecMicro(u32 addr) { +#ifdef VUM_LOG + VUM_LOG("vu0ExecMicro %x\n", addr); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x1; + VU0.VI[REG_VPU_STAT].UL&= ~0xAE; + if (addr != -1) VU0.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU0); + Cpu->ExecuteVU0Block(); +} + +void _vu0ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU0); + VU0_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu0ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU0); + VU0_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); + +void _vu0Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU0.VI[REG_TPC].UL >= VU0.maxmicro){ + #ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + VU->cycle++; + return; + } + + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { + VU->ebit = 2; + } + if (ptr[1] & 0x20000000) { /* M flag */ + VU->flags|= VUFLAG_MFLAGSET; +// SysPrintf("fixme: M flag set\n"); + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x4) { + VU0.VI[REG_VPU_STAT].UL|= 0x2; + hwIntcIrq(INTC_VU0); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x8) { + VU0.VI[REG_VPU_STAT].UL|= 0x4; + hwIntcIrq(INTC_VU0); + } + } + + VU->code = ptr[1]; + VU0regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu0ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + memset(&lregs, 0, sizeof(lregs)); + } else { + VU->code = ptr[0]; + VU0regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU0.VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu0ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu0ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + + if (!(ptr[1] & 0x80000000)) + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + VU->branch--; + if (VU->branch == 0) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */ + vif0Regs->stat&= ~0x4; + } + } +} + +void vu0Exec(VURegs* VU) { +// u32 *ptr; + + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + } else { + _vu0Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU0, VU0); +_vuRegsTables(VU0, VU0regs); + +void VU0unknown() { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU0regsunknown() { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0MI_ABS() { _vuABS(&VU0); } +void VU0MI_ADD() { _vuADD(&VU0); } +void VU0MI_ADDi() { _vuADDi(&VU0); } +void VU0MI_ADDq() { _vuADDq(&VU0); } +void VU0MI_ADDx() { _vuADDx(&VU0); } +void VU0MI_ADDy() { _vuADDy(&VU0); } +void VU0MI_ADDz() { _vuADDz(&VU0); } +void VU0MI_ADDw() { _vuADDw(&VU0); } +void VU0MI_ADDA() { _vuADDA(&VU0); } +void VU0MI_ADDAi() { _vuADDAi(&VU0); } +void VU0MI_ADDAq() { _vuADDAq(&VU0); } +void VU0MI_ADDAx() { _vuADDAx(&VU0); } +void VU0MI_ADDAy() { _vuADDAy(&VU0); } +void VU0MI_ADDAz() { _vuADDAz(&VU0); } +void VU0MI_ADDAw() { _vuADDAw(&VU0); } +void VU0MI_SUB() { _vuSUB(&VU0); } +void VU0MI_SUBi() { _vuSUBi(&VU0); } +void VU0MI_SUBq() { _vuSUBq(&VU0); } +void VU0MI_SUBx() { _vuSUBx(&VU0); } +void VU0MI_SUBy() { _vuSUBy(&VU0); } +void VU0MI_SUBz() { _vuSUBz(&VU0); } +void VU0MI_SUBw() { _vuSUBw(&VU0); } +void VU0MI_SUBA() { _vuSUBA(&VU0); } +void VU0MI_SUBAi() { _vuSUBAi(&VU0); } +void VU0MI_SUBAq() { _vuSUBAq(&VU0); } +void VU0MI_SUBAx() { _vuSUBAx(&VU0); } +void VU0MI_SUBAy() { _vuSUBAy(&VU0); } +void VU0MI_SUBAz() { _vuSUBAz(&VU0); } +void VU0MI_SUBAw() { _vuSUBAw(&VU0); } +void VU0MI_MUL() { _vuMUL(&VU0); } +void VU0MI_MULi() { _vuMULi(&VU0); } +void VU0MI_MULq() { _vuMULq(&VU0); } +void VU0MI_MULx() { _vuMULx(&VU0); } +void VU0MI_MULy() { _vuMULy(&VU0); } +void VU0MI_MULz() { _vuMULz(&VU0); } +void VU0MI_MULw() { _vuMULw(&VU0); } +void VU0MI_MULA() { _vuMULA(&VU0); } +void VU0MI_MULAi() { _vuMULAi(&VU0); } +void VU0MI_MULAq() { _vuMULAq(&VU0); } +void VU0MI_MULAx() { _vuMULAx(&VU0); } +void VU0MI_MULAy() { _vuMULAy(&VU0); } +void VU0MI_MULAz() { _vuMULAz(&VU0); } +void VU0MI_MULAw() { _vuMULAw(&VU0); } +void VU0MI_MADD() { _vuMADD(&VU0); } +void VU0MI_MADDi() { _vuMADDi(&VU0); } +void VU0MI_MADDq() { _vuMADDq(&VU0); } +void VU0MI_MADDx() { _vuMADDx(&VU0); } +void VU0MI_MADDy() { _vuMADDy(&VU0); } +void VU0MI_MADDz() { _vuMADDz(&VU0); } +void VU0MI_MADDw() { _vuMADDw(&VU0); } +void VU0MI_MADDA() { _vuMADDA(&VU0); } +void VU0MI_MADDAi() { _vuMADDAi(&VU0); } +void VU0MI_MADDAq() { _vuMADDAq(&VU0); } +void VU0MI_MADDAx() { _vuMADDAx(&VU0); } +void VU0MI_MADDAy() { _vuMADDAy(&VU0); } +void VU0MI_MADDAz() { _vuMADDAz(&VU0); } +void VU0MI_MADDAw() { _vuMADDAw(&VU0); } +void VU0MI_MSUB() { _vuMSUB(&VU0); } +void VU0MI_MSUBi() { _vuMSUBi(&VU0); } +void VU0MI_MSUBq() { _vuMSUBq(&VU0); } +void VU0MI_MSUBx() { _vuMSUBx(&VU0); } +void VU0MI_MSUBy() { _vuMSUBy(&VU0); } +void VU0MI_MSUBz() { _vuMSUBz(&VU0); } +void VU0MI_MSUBw() { _vuMSUBw(&VU0); } +void VU0MI_MSUBA() { _vuMSUBA(&VU0); } +void VU0MI_MSUBAi() { _vuMSUBAi(&VU0); } +void VU0MI_MSUBAq() { _vuMSUBAq(&VU0); } +void VU0MI_MSUBAx() { _vuMSUBAx(&VU0); } +void VU0MI_MSUBAy() { _vuMSUBAy(&VU0); } +void VU0MI_MSUBAz() { _vuMSUBAz(&VU0); } +void VU0MI_MSUBAw() { _vuMSUBAw(&VU0); } +void VU0MI_MAX() { _vuMAX(&VU0); } +void VU0MI_MAXi() { _vuMAXi(&VU0); } +void VU0MI_MAXx() { _vuMAXx(&VU0); } +void VU0MI_MAXy() { _vuMAXy(&VU0); } +void VU0MI_MAXz() { _vuMAXz(&VU0); } +void VU0MI_MAXw() { _vuMAXw(&VU0); } +void VU0MI_MINI() { _vuMINI(&VU0); } +void VU0MI_MINIi() { _vuMINIi(&VU0); } +void VU0MI_MINIx() { _vuMINIx(&VU0); } +void VU0MI_MINIy() { _vuMINIy(&VU0); } +void VU0MI_MINIz() { _vuMINIz(&VU0); } +void VU0MI_MINIw() { _vuMINIw(&VU0); } +void VU0MI_OPMULA() { _vuOPMULA(&VU0); } +void VU0MI_OPMSUB() { _vuOPMSUB(&VU0); } +void VU0MI_NOP() { _vuNOP(&VU0); } +void VU0MI_FTOI0() { _vuFTOI0(&VU0); } +void VU0MI_FTOI4() { _vuFTOI4(&VU0); } +void VU0MI_FTOI12() { _vuFTOI12(&VU0); } +void VU0MI_FTOI15() { _vuFTOI15(&VU0); } +void VU0MI_ITOF0() { _vuITOF0(&VU0); } +void VU0MI_ITOF4() { _vuITOF4(&VU0); } +void VU0MI_ITOF12() { _vuITOF12(&VU0); } +void VU0MI_ITOF15() { _vuITOF15(&VU0); } +void VU0MI_CLIP() { _vuCLIP(&VU0); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0MI_DIV() { _vuDIV(&VU0); } +void VU0MI_SQRT() { _vuSQRT(&VU0); } +void VU0MI_RSQRT() { _vuRSQRT(&VU0); } +void VU0MI_IADD() { _vuIADD(&VU0); } +void VU0MI_IADDI() { _vuIADDI(&VU0); } +void VU0MI_IADDIU() { _vuIADDIU(&VU0); } +void VU0MI_IAND() { _vuIAND(&VU0); } +void VU0MI_IOR() { _vuIOR(&VU0); } +void VU0MI_ISUB() { _vuISUB(&VU0); } +void VU0MI_ISUBIU() { _vuISUBIU(&VU0); } +void VU0MI_MOVE() { _vuMOVE(&VU0); } +void VU0MI_MFIR() { _vuMFIR(&VU0); } +void VU0MI_MTIR() { _vuMTIR(&VU0); } +void VU0MI_MR32() { _vuMR32(&VU0); } +void VU0MI_LQ() { _vuLQ(&VU0); } +void VU0MI_LQD() { _vuLQD(&VU0); } +void VU0MI_LQI() { _vuLQI(&VU0); } +void VU0MI_SQ() { _vuSQ(&VU0); } +void VU0MI_SQD() { _vuSQD(&VU0); } +void VU0MI_SQI() { _vuSQI(&VU0); } +void VU0MI_ILW() { _vuILW(&VU0); } +void VU0MI_ISW() { _vuISW(&VU0); } +void VU0MI_ILWR() { _vuILWR(&VU0); } +void VU0MI_ISWR() { _vuISWR(&VU0); } +void VU0MI_RINIT() { _vuRINIT(&VU0); } +void VU0MI_RGET() { _vuRGET(&VU0); } +void VU0MI_RNEXT() { _vuRNEXT(&VU0); } +void VU0MI_RXOR() { _vuRXOR(&VU0); } +void VU0MI_WAITQ() { _vuWAITQ(&VU0); } +void VU0MI_FSAND() { _vuFSAND(&VU0); } +void VU0MI_FSEQ() { _vuFSEQ(&VU0); } +void VU0MI_FSOR() { _vuFSOR(&VU0); } +void VU0MI_FSSET() { _vuFSSET(&VU0); } +void VU0MI_FMAND() { _vuFMAND(&VU0); } +void VU0MI_FMEQ() { _vuFMEQ(&VU0); } +void VU0MI_FMOR() { _vuFMOR(&VU0); } +void VU0MI_FCAND() { _vuFCAND(&VU0); } +void VU0MI_FCEQ() { _vuFCEQ(&VU0); } +void VU0MI_FCOR() { _vuFCOR(&VU0); } +void VU0MI_FCSET() { _vuFCSET(&VU0); } +void VU0MI_FCGET() { _vuFCGET(&VU0); } +void VU0MI_IBEQ() { _vuIBEQ(&VU0); } +void VU0MI_IBGEZ() { _vuIBGEZ(&VU0); } +void VU0MI_IBGTZ() { _vuIBGTZ(&VU0); } +void VU0MI_IBLTZ() { _vuIBLTZ(&VU0); } +void VU0MI_IBLEZ() { _vuIBLEZ(&VU0); } +void VU0MI_IBNE() { _vuIBNE(&VU0); } +void VU0MI_B() { _vuB(&VU0); } +void VU0MI_BAL() { _vuBAL(&VU0); } +void VU0MI_JR() { _vuJR(&VU0); } +void VU0MI_JALR() { _vuJALR(&VU0); } +void VU0MI_MFP() { _vuMFP(&VU0); } +void VU0MI_WAITP() { _vuWAITP(&VU0); } +void VU0MI_ESADD() { _vuESADD(&VU0); } +void VU0MI_ERSADD() { _vuERSADD(&VU0); } +void VU0MI_ELENG() { _vuELENG(&VU0); } +void VU0MI_ERLENG() { _vuERLENG(&VU0); } +void VU0MI_EATANxy() { _vuEATANxy(&VU0); } +void VU0MI_EATANxz() { _vuEATANxz(&VU0); } +void VU0MI_ESUM() { _vuESUM(&VU0); } +void VU0MI_ERCPR() { _vuERCPR(&VU0); } +void VU0MI_ESQRT() { _vuESQRT(&VU0); } +void VU0MI_ERSQRT() { _vuERSQRT(&VU0); } +void VU0MI_ESIN() { _vuESIN(&VU0); } +void VU0MI_EATAN() { _vuEATAN(&VU0); } +void VU0MI_EEXP() { _vuEEXP(&VU0); } +void VU0MI_XITOP() { _vuXITOP(&VU0); } + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU0, VUregsn); } +void VU0regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU0, VUregsn); } +void VU0regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU0, VUregsn); } +void VU0regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU0, VUregsn); } +void VU0regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU0, VUregsn); } +void VU0regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU0, VUregsn); } +void VU0regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU0, VUregsn); } +void VU0regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU0, VUregsn); } +void VU0regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU0, VUregsn); } +void VU0regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU0, VUregsn); } +void VU0regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU0, VUregsn); } +void VU0regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU0, VUregsn); } +void VU0regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU0, VUregsn); } +void VU0regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU0, VUregsn); } +void VU0regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU0, VUregsn); } +void VU0regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU0, VUregsn); } +void VU0regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU0, VUregsn); } +void VU0regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU0, VUregsn); } +void VU0regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU0, VUregsn); } +void VU0regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU0, VUregsn); } +void VU0regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU0, VUregsn); } +void VU0regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU0, VUregsn); } +void VU0regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU0, VUregsn); } +void VU0regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU0, VUregsn); } +void VU0regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU0, VUregsn); } +void VU0regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU0, VUregsn); } +void VU0regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU0, VUregsn); } +void VU0regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU0, VUregsn); } +void VU0regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU0, VUregsn); } +void VU0regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU0, VUregsn); } +void VU0regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU0, VUregsn); } +void VU0regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU0, VUregsn); } +void VU0regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU0, VUregsn); } +void VU0regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU0, VUregsn); } +void VU0regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU0, VUregsn); } +void VU0regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU0, VUregsn); } +void VU0regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU0, VUregsn); } +void VU0regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU0, VUregsn); } +void VU0regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU0, VUregsn); } +void VU0regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU0, VUregsn); } +void VU0regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU0, VUregsn); } +void VU0regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU0, VUregsn); } +void VU0regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU0, VUregsn); } +void VU0regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU0, VUregsn); } +void VU0regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU0, VUregsn); } +void VU0regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU0, VUregsn); } +void VU0regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU0, VUregsn); } +void VU0regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU0, VUregsn); } +void VU0regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU0, VUregsn); } +void VU0regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU0, VUregsn); } +void VU0regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU0, VUregsn); } +void VU0regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU0, VUregsn); } +void VU0regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU0, VUregsn); } +void VU0regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU0, VUregsn); } +void VU0regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU0, VUregsn); } +void VU0regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU0, VUregsn); } +void VU0regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU0, VUregsn); } +void VU0regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU0, VUregsn); } +void VU0regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU0, VUregsn); } +void VU0regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU0, VUregsn); } +void VU0regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU0, VUregsn); } +void VU0regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU0, VUregsn); } +void VU0regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU0, VUregsn); } +void VU0regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU0, VUregsn); } +void VU0regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU0, VUregsn); } +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU0, VUregsn); } +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU0, VUregsn); } +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU0, VUregsn); } +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU0, VUregsn); } +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU0, VUregsn); } +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU0, VUregsn); } +void VU0regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU0, VUregsn); } +void VU0regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU0, VUregsn); } +void VU0regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU0, VUregsn); } +void VU0regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU0, VUregsn); } +void VU0regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU0, VUregsn); } +void VU0regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU0, VUregsn); } +void VU0regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU0, VUregsn); } +void VU0regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU0, VUregsn); } +void VU0regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU0, VUregsn); } +void VU0regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU0, VUregsn); } +void VU0regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU0, VUregsn); } +void VU0regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU0, VUregsn); } +void VU0regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU0, VUregsn); } +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU0, VUregsn); } +void VU0regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU0, VUregsn); } +void VU0regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU0, VUregsn); } +void VU0regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU0, VUregsn); } +void VU0regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU0, VUregsn); } +void VU0regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU0, VUregsn); } +void VU0regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU0, VUregsn); } +void VU0regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU0, VUregsn); } +void VU0regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU0, VUregsn); } +void VU0regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU0, VUregsn); } +void VU0regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU0, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU0, VUregsn); } +void VU0regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU0, VUregsn); } +void VU0regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU0, VUregsn); } +void VU0regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU0, VUregsn); } +void VU0regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU0, VUregsn); } +void VU0regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU0, VUregsn); } +void VU0regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU0, VUregsn); } +void VU0regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU0, VUregsn); } +void VU0regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU0, VUregsn); } +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU0, VUregsn); } +void VU0regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU0, VUregsn); } +void VU0regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU0, VUregsn); } +void VU0regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU0, VUregsn); } +void VU0regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU0, VUregsn); } +void VU0regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU0, VUregsn); } +void VU0regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU0, VUregsn); } +void VU0regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU0, VUregsn); } +void VU0regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU0, VUregsn); } +void VU0regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU0, VUregsn); } +void VU0regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU0, VUregsn); } +void VU0regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU0, VUregsn); } +void VU0regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU0, VUregsn); } +void VU0regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU0, VUregsn); } +void VU0regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU0, VUregsn); } +void VU0regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU0, VUregsn); } +void VU0regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU0, VUregsn); } +void VU0regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU0, VUregsn); } +void VU0regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU0, VUregsn); } +void VU0regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU0, VUregsn); } +void VU0regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU0, VUregsn); } +void VU0regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU0, VUregsn); } +void VU0regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU0, VUregsn); } +void VU0regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU0, VUregsn); } +void VU0regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU0, VUregsn); } +void VU0regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU0, VUregsn); } +void VU0regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU0, VUregsn); } +void VU0regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU0, VUregsn); } +void VU0regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU0, VUregsn); } +void VU0regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU0, VUregsn); } +void VU0regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU0, VUregsn); } +void VU0regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU0, VUregsn); } +void VU0regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU0, VUregsn); } +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU0, VUregsn); } +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU0, VUregsn); } +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU0, VUregsn); } +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU0, VUregsn); } +void VU0regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU0, VUregsn); } +void VU0regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU0, VUregsn); } +void VU0regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU0, VUregsn); } +void VU0regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU0, VUregsn); } +void VU0regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU0, VUregsn); } +void VU0regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU0, VUregsn); } +void VU0regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU0, VUregsn); } +void VU0regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU0, VUregsn); } +void VU0regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU0, VUregsn); } +void VU0regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU0, VUregsn); } +void VU0regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU0, VUregsn); } +void VU0regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU0, VUregsn); } +void VU0regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU0, VUregsn); } +void VU0regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU0, VUregsn); } +void VU0regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU0, VUregsn); } +void VU0regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU0, VUregsn); } +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU0, VUregsn); } +void VU0regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU0, VUregsn); } +void VU0regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU0, VUregsn); } +void VU0regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU0, VUregsn); } +void VU0regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU0, VUregsn); } +void VU0regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU0, VUregsn); } +void VU0regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU0, VUregsn); } diff --git a/VU1micro.c b/VU1micro.c new file mode 100644 index 0000000000..ca72f87732 --- /dev/null +++ b/VU1micro.c @@ -0,0 +1,665 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUops.h" +#include "VUflags.h" +#include "ivu1micro.h" + +#include "iVUzerorec.h" + +VURegs* g_pVU1; + +#ifdef WIN32_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +#endif + +#ifdef __MSCW32__ +#pragma warning(disable:4113) +#endif + +int vu1Init() +{ + assert( VU0.Mem != NULL ); + g_pVU1 = (VURegs*)(VU0.Mem + 0x4000); + +#ifdef WIN32_VIRTUAL_MEM + VU1.Mem = PS2MEM_VU1MEM; + VU1.Micro = PS2MEM_VU1MICRO; +#else + VU1.Mem = (u8*)_aligned_malloc(16*1024, 16); + VU1.Micro = (u8*)_aligned_malloc(16*1024, 16); + if (VU1.Mem == NULL || VU1.Micro == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + memset(VU1.Mem, 0,16*1024); + memset(VU1.Micro, 0,16*1024); +#endif + + VU1.maxmem = -1;//16*1024-4; + VU1.maxmicro = 16*1024-4; +// VU1.VF = (VECTOR*)(VU0.Mem + 0x4000); +// VU1.VI = (REG_VI*)(VU0.Mem + 0x4200); + VU1.vuExec = vu1Exec; + VU1.vifRegs = vif1Regs; + + if( CHECK_VU1REC ) { + recVU1Init(); + } + + vu1Reset(); + + return 0; +} + +void vu1Shutdown() { + if( CHECK_VU1REC ) { + recVU1Shutdown(); + } +} + +void vu1ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1 + VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1 + vif1Regs->stat &= ~4; +} + +void vu1Reset() { + memset(&VU1.ACC, 0, sizeof(VECTOR)); + memset(VU1.VF, 0, sizeof(VECTOR)*32); + memset(VU1.VI, 0, sizeof(REG_VI)*32); + VU1.VF[0].f.x = 0.0f; + VU1.VF[0].f.y = 0.0f; + VU1.VF[0].f.z = 0.0f; + VU1.VF[0].f.w = 1.0f; + VU1.VI[0].UL = 0; + memset(VU1.Mem, 0, 16*1024); + memset(VU1.Micro, 0, 16*1024); + + recResetVU1(); +} + +void vu1Freeze(gzFile f, int Mode) { + gzfreeze(&VU1.ACC, sizeof(VECTOR)); + gzfreeze(&VU1.code, sizeof(u32)); + gzfreeze(VU1.Mem, 16*1024); + gzfreeze(VU1.Micro, 16*1024); + gzfreeze(VU1.VF, 32*sizeof(VECTOR)); + gzfreeze(VU1.VI, 32*sizeof(REG_VI)); +} + +static int count; + +void vu1ExecMicro(u32 addr) +{ +#ifdef VUM_LOG + VUM_LOG("vu1ExecMicro %x\n", addr); + VUM_LOG("vu1ExecMicro %x (count=%d)\n", addr, count++); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x100; + VU0.VI[REG_VPU_STAT].UL&= ~0x7E000; + vif1Regs->stat|= 0x4; + if (addr != -1) VU1.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU1); + + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU1Block(); + } while(VU0.VI[REG_VPU_STAT].UL & 0x100); + // rec can call vu1ExecMicro + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void _vu1ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU1); + VU1_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu1ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU1); + VU1_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); + +void _vu1Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU1.VI[REG_TPC].UL >= VU1.maxmicro){ +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { /* E flag */ + VU->ebit = 2; + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x400) { + VU0.VI[REG_VPU_STAT].UL|= 0x200; + hwIntcIrq(INTC_VU1); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x800) { + VU0.VI[REG_VPU_STAT].UL|= 0x400; + hwIntcIrq(INTC_VU1); + } + } + +#ifdef VUM_LOG + if (Log) { + VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)\n", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F); + } +#endif + + VU->code = ptr[1]; + VU1regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu1ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + } else { + VU->code = ptr[0]; + VU1regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU->VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu1ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu1ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + if (VU->branch-- == 1) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + vif1Regs->stat&= ~0x4; + } + } +} + +void vu1Exec(VURegs* VU) { + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + } else { + _vu1Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU1, VU1); +_vuRegsTables(VU1, VU1regs); + +void VU1unknown() { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU1regsunknown() { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1MI_ABS() { _vuABS(&VU1); } +void VU1MI_ADD() { _vuADD(&VU1); } +void VU1MI_ADDi() { _vuADDi(&VU1); } +void VU1MI_ADDq() { _vuADDq(&VU1); } +void VU1MI_ADDx() { _vuADDx(&VU1); } +void VU1MI_ADDy() { _vuADDy(&VU1); } +void VU1MI_ADDz() { _vuADDz(&VU1); } +void VU1MI_ADDw() { _vuADDw(&VU1); } +void VU1MI_ADDA() { _vuADDA(&VU1); } +void VU1MI_ADDAi() { _vuADDAi(&VU1); } +void VU1MI_ADDAq() { _vuADDAq(&VU1); } +void VU1MI_ADDAx() { _vuADDAx(&VU1); } +void VU1MI_ADDAy() { _vuADDAy(&VU1); } +void VU1MI_ADDAz() { _vuADDAz(&VU1); } +void VU1MI_ADDAw() { _vuADDAw(&VU1); } +void VU1MI_SUB() { _vuSUB(&VU1); } +void VU1MI_SUBi() { _vuSUBi(&VU1); } +void VU1MI_SUBq() { _vuSUBq(&VU1); } +void VU1MI_SUBx() { _vuSUBx(&VU1); } +void VU1MI_SUBy() { _vuSUBy(&VU1); } +void VU1MI_SUBz() { _vuSUBz(&VU1); } +void VU1MI_SUBw() { _vuSUBw(&VU1); } +void VU1MI_SUBA() { _vuSUBA(&VU1); } +void VU1MI_SUBAi() { _vuSUBAi(&VU1); } +void VU1MI_SUBAq() { _vuSUBAq(&VU1); } +void VU1MI_SUBAx() { _vuSUBAx(&VU1); } +void VU1MI_SUBAy() { _vuSUBAy(&VU1); } +void VU1MI_SUBAz() { _vuSUBAz(&VU1); } +void VU1MI_SUBAw() { _vuSUBAw(&VU1); } +void VU1MI_MUL() { _vuMUL(&VU1); } +void VU1MI_MULi() { _vuMULi(&VU1); } +void VU1MI_MULq() { _vuMULq(&VU1); } +void VU1MI_MULx() { _vuMULx(&VU1); } +void VU1MI_MULy() { _vuMULy(&VU1); } +void VU1MI_MULz() { _vuMULz(&VU1); } +void VU1MI_MULw() { _vuMULw(&VU1); } +void VU1MI_MULA() { _vuMULA(&VU1); } +void VU1MI_MULAi() { _vuMULAi(&VU1); } +void VU1MI_MULAq() { _vuMULAq(&VU1); } +void VU1MI_MULAx() { _vuMULAx(&VU1); } +void VU1MI_MULAy() { _vuMULAy(&VU1); } +void VU1MI_MULAz() { _vuMULAz(&VU1); } +void VU1MI_MULAw() { _vuMULAw(&VU1); } +void VU1MI_MADD() { _vuMADD(&VU1); } +void VU1MI_MADDi() { _vuMADDi(&VU1); } +void VU1MI_MADDq() { _vuMADDq(&VU1); } +void VU1MI_MADDx() { _vuMADDx(&VU1); } +void VU1MI_MADDy() { _vuMADDy(&VU1); } +void VU1MI_MADDz() { _vuMADDz(&VU1); } +void VU1MI_MADDw() { _vuMADDw(&VU1); } +void VU1MI_MADDA() { _vuMADDA(&VU1); } +void VU1MI_MADDAi() { _vuMADDAi(&VU1); } +void VU1MI_MADDAq() { _vuMADDAq(&VU1); } +void VU1MI_MADDAx() { _vuMADDAx(&VU1); } +void VU1MI_MADDAy() { _vuMADDAy(&VU1); } +void VU1MI_MADDAz() { _vuMADDAz(&VU1); } +void VU1MI_MADDAw() { _vuMADDAw(&VU1); } +void VU1MI_MSUB() { _vuMSUB(&VU1); } +void VU1MI_MSUBi() { _vuMSUBi(&VU1); } +void VU1MI_MSUBq() { _vuMSUBq(&VU1); } +void VU1MI_MSUBx() { _vuMSUBx(&VU1); } +void VU1MI_MSUBy() { _vuMSUBy(&VU1); } +void VU1MI_MSUBz() { _vuMSUBz(&VU1); } +void VU1MI_MSUBw() { _vuMSUBw(&VU1); } +void VU1MI_MSUBA() { _vuMSUBA(&VU1); } +void VU1MI_MSUBAi() { _vuMSUBAi(&VU1); } +void VU1MI_MSUBAq() { _vuMSUBAq(&VU1); } +void VU1MI_MSUBAx() { _vuMSUBAx(&VU1); } +void VU1MI_MSUBAy() { _vuMSUBAy(&VU1); } +void VU1MI_MSUBAz() { _vuMSUBAz(&VU1); } +void VU1MI_MSUBAw() { _vuMSUBAw(&VU1); } +void VU1MI_MAX() { _vuMAX(&VU1); } +void VU1MI_MAXi() { _vuMAXi(&VU1); } +void VU1MI_MAXx() { _vuMAXx(&VU1); } +void VU1MI_MAXy() { _vuMAXy(&VU1); } +void VU1MI_MAXz() { _vuMAXz(&VU1); } +void VU1MI_MAXw() { _vuMAXw(&VU1); } +void VU1MI_MINI() { _vuMINI(&VU1); } +void VU1MI_MINIi() { _vuMINIi(&VU1); } +void VU1MI_MINIx() { _vuMINIx(&VU1); } +void VU1MI_MINIy() { _vuMINIy(&VU1); } +void VU1MI_MINIz() { _vuMINIz(&VU1); } +void VU1MI_MINIw() { _vuMINIw(&VU1); } +void VU1MI_OPMULA() { _vuOPMULA(&VU1); } +void VU1MI_OPMSUB() { _vuOPMSUB(&VU1); } +void VU1MI_NOP() { _vuNOP(&VU1); } +void VU1MI_FTOI0() { _vuFTOI0(&VU1); } +void VU1MI_FTOI4() { _vuFTOI4(&VU1); } +void VU1MI_FTOI12() { _vuFTOI12(&VU1); } +void VU1MI_FTOI15() { _vuFTOI15(&VU1); } +void VU1MI_ITOF0() { _vuITOF0(&VU1); } +void VU1MI_ITOF4() { _vuITOF4(&VU1); } +void VU1MI_ITOF12() { _vuITOF12(&VU1); } +void VU1MI_ITOF15() { _vuITOF15(&VU1); } +void VU1MI_CLIP() { _vuCLIP(&VU1); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1MI_DIV() { _vuDIV(&VU1); } +void VU1MI_SQRT() { _vuSQRT(&VU1); } +void VU1MI_RSQRT() { _vuRSQRT(&VU1); } +void VU1MI_IADD() { _vuIADD(&VU1); } +void VU1MI_IADDI() { _vuIADDI(&VU1); } +void VU1MI_IADDIU() { _vuIADDIU(&VU1); } +void VU1MI_IAND() { _vuIAND(&VU1); } +void VU1MI_IOR() { _vuIOR(&VU1); } +void VU1MI_ISUB() { _vuISUB(&VU1); } +void VU1MI_ISUBIU() { _vuISUBIU(&VU1); } +void VU1MI_MOVE() { _vuMOVE(&VU1); } +void VU1MI_MFIR() { _vuMFIR(&VU1); } +void VU1MI_MTIR() { _vuMTIR(&VU1); } +void VU1MI_MR32() { _vuMR32(&VU1); } +void VU1MI_LQ() { _vuLQ(&VU1); } +void VU1MI_LQD() { _vuLQD(&VU1); } +void VU1MI_LQI() { _vuLQI(&VU1); } +void VU1MI_SQ() { _vuSQ(&VU1); } +void VU1MI_SQD() { _vuSQD(&VU1); } +void VU1MI_SQI() { _vuSQI(&VU1); } +void VU1MI_ILW() { _vuILW(&VU1); } +void VU1MI_ISW() { _vuISW(&VU1); } +void VU1MI_ILWR() { _vuILWR(&VU1); } +void VU1MI_ISWR() { _vuISWR(&VU1); } +void VU1MI_RINIT() { _vuRINIT(&VU1); } +void VU1MI_RGET() { _vuRGET(&VU1); } +void VU1MI_RNEXT() { _vuRNEXT(&VU1); } +void VU1MI_RXOR() { _vuRXOR(&VU1); } +void VU1MI_WAITQ() { _vuWAITQ(&VU1); } +void VU1MI_FSAND() { _vuFSAND(&VU1); } +void VU1MI_FSEQ() { _vuFSEQ(&VU1); } +void VU1MI_FSOR() { _vuFSOR(&VU1); } +void VU1MI_FSSET() { _vuFSSET(&VU1); } +void VU1MI_FMAND() { _vuFMAND(&VU1); } +void VU1MI_FMEQ() { _vuFMEQ(&VU1); } +void VU1MI_FMOR() { _vuFMOR(&VU1); } +void VU1MI_FCAND() { _vuFCAND(&VU1); } +void VU1MI_FCEQ() { _vuFCEQ(&VU1); } +void VU1MI_FCOR() { _vuFCOR(&VU1); } +void VU1MI_FCSET() { _vuFCSET(&VU1); } +void VU1MI_FCGET() { _vuFCGET(&VU1); } +void VU1MI_IBEQ() { _vuIBEQ(&VU1); } +void VU1MI_IBGEZ() { _vuIBGEZ(&VU1); } +void VU1MI_IBGTZ() { _vuIBGTZ(&VU1); } +void VU1MI_IBLTZ() { _vuIBLTZ(&VU1); } +void VU1MI_IBLEZ() { _vuIBLEZ(&VU1); } +void VU1MI_IBNE() { _vuIBNE(&VU1); } +void VU1MI_B() { _vuB(&VU1); } +void VU1MI_BAL() { _vuBAL(&VU1); } +void VU1MI_JR() { _vuJR(&VU1); } +void VU1MI_JALR() { _vuJALR(&VU1); } +void VU1MI_MFP() { _vuMFP(&VU1); } +void VU1MI_WAITP() { _vuWAITP(&VU1); } +void VU1MI_ESADD() { _vuESADD(&VU1); } +void VU1MI_ERSADD() { _vuERSADD(&VU1); } +void VU1MI_ELENG() { _vuELENG(&VU1); } +void VU1MI_ERLENG() { _vuERLENG(&VU1); } +void VU1MI_EATANxy() { _vuEATANxy(&VU1); } +void VU1MI_EATANxz() { _vuEATANxz(&VU1); } +void VU1MI_ESUM() { _vuESUM(&VU1); } +void VU1MI_ERCPR() { _vuERCPR(&VU1); } +void VU1MI_ESQRT() { _vuESQRT(&VU1); } +void VU1MI_ERSQRT() { _vuERSQRT(&VU1); } +void VU1MI_ESIN() { _vuESIN(&VU1); } +void VU1MI_EATAN() { _vuEATAN(&VU1); } +void VU1MI_EEXP() { _vuEEXP(&VU1); } +void VU1MI_XITOP() { _vuXITOP(&VU1); } +void VU1MI_XGKICK() { _vuXGKICK(&VU1); } +void VU1MI_XTOP() { _vuXTOP(&VU1); } + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU1, VUregsn); } +void VU1regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU1, VUregsn); } +void VU1regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU1, VUregsn); } +void VU1regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU1, VUregsn); } +void VU1regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU1, VUregsn); } +void VU1regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU1, VUregsn); } +void VU1regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU1, VUregsn); } +void VU1regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU1, VUregsn); } +void VU1regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU1, VUregsn); } +void VU1regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU1, VUregsn); } +void VU1regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU1, VUregsn); } +void VU1regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU1, VUregsn); } +void VU1regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU1, VUregsn); } +void VU1regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU1, VUregsn); } +void VU1regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU1, VUregsn); } +void VU1regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU1, VUregsn); } +void VU1regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU1, VUregsn); } +void VU1regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU1, VUregsn); } +void VU1regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU1, VUregsn); } +void VU1regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU1, VUregsn); } +void VU1regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU1, VUregsn); } +void VU1regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU1, VUregsn); } +void VU1regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU1, VUregsn); } +void VU1regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU1, VUregsn); } +void VU1regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU1, VUregsn); } +void VU1regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU1, VUregsn); } +void VU1regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU1, VUregsn); } +void VU1regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU1, VUregsn); } +void VU1regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU1, VUregsn); } +void VU1regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU1, VUregsn); } +void VU1regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU1, VUregsn); } +void VU1regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU1, VUregsn); } +void VU1regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU1, VUregsn); } +void VU1regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU1, VUregsn); } +void VU1regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU1, VUregsn); } +void VU1regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU1, VUregsn); } +void VU1regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU1, VUregsn); } +void VU1regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU1, VUregsn); } +void VU1regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU1, VUregsn); } +void VU1regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU1, VUregsn); } +void VU1regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU1, VUregsn); } +void VU1regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU1, VUregsn); } +void VU1regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU1, VUregsn); } +void VU1regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU1, VUregsn); } +void VU1regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU1, VUregsn); } +void VU1regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU1, VUregsn); } +void VU1regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU1, VUregsn); } +void VU1regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU1, VUregsn); } +void VU1regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU1, VUregsn); } +void VU1regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU1, VUregsn); } +void VU1regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU1, VUregsn); } +void VU1regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU1, VUregsn); } +void VU1regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU1, VUregsn); } +void VU1regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU1, VUregsn); } +void VU1regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU1, VUregsn); } +void VU1regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU1, VUregsn); } +void VU1regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU1, VUregsn); } +void VU1regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU1, VUregsn); } +void VU1regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU1, VUregsn); } +void VU1regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU1, VUregsn); } +void VU1regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU1, VUregsn); } +void VU1regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU1, VUregsn); } +void VU1regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU1, VUregsn); } +void VU1regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU1, VUregsn); } +void VU1regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU1, VUregsn); } +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU1, VUregsn); } +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU1, VUregsn); } +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU1, VUregsn); } +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU1, VUregsn); } +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU1, VUregsn); } +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU1, VUregsn); } +void VU1regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU1, VUregsn); } +void VU1regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU1, VUregsn); } +void VU1regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU1, VUregsn); } +void VU1regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU1, VUregsn); } +void VU1regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU1, VUregsn); } +void VU1regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU1, VUregsn); } +void VU1regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU1, VUregsn); } +void VU1regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU1, VUregsn); } +void VU1regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU1, VUregsn); } +void VU1regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU1, VUregsn); } +void VU1regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU1, VUregsn); } +void VU1regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU1, VUregsn); } +void VU1regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU1, VUregsn); } +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU1, VUregsn); } +void VU1regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU1, VUregsn); } +void VU1regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU1, VUregsn); } +void VU1regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU1, VUregsn); } +void VU1regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU1, VUregsn); } +void VU1regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU1, VUregsn); } +void VU1regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU1, VUregsn); } +void VU1regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU1, VUregsn); } +void VU1regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU1, VUregsn); } +void VU1regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU1, VUregsn); } +void VU1regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU1, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU1, VUregsn); } +void VU1regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU1, VUregsn); } +void VU1regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU1, VUregsn); } +void VU1regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU1, VUregsn); } +void VU1regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU1, VUregsn); } +void VU1regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU1, VUregsn); } +void VU1regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU1, VUregsn); } +void VU1regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU1, VUregsn); } +void VU1regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU1, VUregsn); } +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU1, VUregsn); } +void VU1regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU1, VUregsn); } +void VU1regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU1, VUregsn); } +void VU1regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU1, VUregsn); } +void VU1regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU1, VUregsn); } +void VU1regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU1, VUregsn); } +void VU1regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU1, VUregsn); } +void VU1regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU1, VUregsn); } +void VU1regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU1, VUregsn); } +void VU1regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU1, VUregsn); } +void VU1regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU1, VUregsn); } +void VU1regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU1, VUregsn); } +void VU1regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU1, VUregsn); } +void VU1regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU1, VUregsn); } +void VU1regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU1, VUregsn); } +void VU1regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU1, VUregsn); } +void VU1regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU1, VUregsn); } +void VU1regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU1, VUregsn); } +void VU1regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU1, VUregsn); } +void VU1regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU1, VUregsn); } +void VU1regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU1, VUregsn); } +void VU1regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU1, VUregsn); } +void VU1regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU1, VUregsn); } +void VU1regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU1, VUregsn); } +void VU1regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU1, VUregsn); } +void VU1regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU1, VUregsn); } +void VU1regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU1, VUregsn); } +void VU1regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU1, VUregsn); } +void VU1regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU1, VUregsn); } +void VU1regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU1, VUregsn); } +void VU1regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU1, VUregsn); } +void VU1regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU1, VUregsn); } +void VU1regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU1, VUregsn); } +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU1, VUregsn); } +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU1, VUregsn); } +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU1, VUregsn); } +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU1, VUregsn); } +void VU1regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU1, VUregsn); } +void VU1regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU1, VUregsn); } +void VU1regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU1, VUregsn); } +void VU1regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU1, VUregsn); } +void VU1regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU1, VUregsn); } +void VU1regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU1, VUregsn); } +void VU1regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU1, VUregsn); } +void VU1regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU1, VUregsn); } +void VU1regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU1, VUregsn); } +void VU1regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU1, VUregsn); } +void VU1regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU1, VUregsn); } +void VU1regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU1, VUregsn); } +void VU1regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU1, VUregsn); } +void VU1regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU1, VUregsn); } +void VU1regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU1, VUregsn); } +void VU1regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU1, VUregsn); } +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU1, VUregsn); } +void VU1regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU1, VUregsn); } +void VU1regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU1, VUregsn); } +void VU1regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU1, VUregsn); } +void VU1regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU1, VUregsn); } +void VU1regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU1, VUregsn); } +void VU1regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU1, VUregsn); } diff --git a/VUflags.c b/VUflags.c new file mode 100644 index 0000000000..637d564620 --- /dev/null +++ b/VUflags.c @@ -0,0 +1,96 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +/*****************************************/ +/* NEW FLAGS */ //By asadr. Thnkx F|RES :p +/*****************************************/ + + +__inline void vuUpdateDI(VURegs * VU) { +// u32 Flag_S = 0; +// u32 Flag_I = 0; +// u32 Flag_D = 0; +// +// /* +// FLAG D - I +// */ +// Flag_I = (VU->statusflag >> 4) & 0x1; +// Flag_D = (VU->statusflag >> 5) & 0x1; +// +// VU->statusflag|= (Flag_I | (VU0.VI[REG_STATUS_FLAG].US[0] >> 4)) << 10; +// VU->statusflag|= (Flag_D | (VU0.VI[REG_STATUS_FLAG].US[0] >> 5)) << 11; +} + +#define VU_MAC_UPDATE(name, shift) \ +u32 name(VURegs * VU, float f) { \ + u32 v = *(u32*)&f; \ + int exp = (v >> 23) & 0xff; \ + u32 s = v & 0x80000000; \ + \ + if (s) VU->macflag |= 0x0010<macflag &= ~(0x0010<macflag = (VU->macflag & ~(0x1100<macflag = (VU->macflag&~(0x1000<macflag = (VU->macflag&~(0x0100<macflag = (VU->macflag & ~(0x1101<macflag&= ~(0x1111<macflag & 0x000F) newflag = 0x1; + if (VU->macflag & 0x00F0) newflag |= 0x2; + if (VU->macflag & 0x0F00) newflag |= 0x4; + if (VU->macflag & 0xF000) newflag |= 0x8; + VU->statusflag = (VU->statusflag&0xc30)|newflag|((VU->statusflag&0xf)<<6); +} diff --git a/VUflags.h b/VUflags.h new file mode 100644 index 0000000000..37338a5d30 --- /dev/null +++ b/VUflags.h @@ -0,0 +1,38 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUFLAGS_H__ +#define __VUFLAGS_H__ + +#include "VU.h" + +void vuUpdateDI(VURegs * VU); +u32 VU_MACx_UPDATE(VURegs * VU, float x); +u32 VU_MACy_UPDATE(VURegs * VU, float y); +u32 VU_MACz_UPDATE(VURegs * VU, float z); +u32 VU_MACw_UPDATE(VURegs * VU, float w); +void VU_MACx_CLEAR(VURegs * VU); +void VU_MACy_CLEAR(VURegs * VU); +void VU_MACz_CLEAR(VURegs * VU); +void VU_MACw_CLEAR(VURegs * VU); +void VU_STAT_UPDATE(VURegs * VU); + + +#endif + + diff --git a/VUmicro.h b/VUmicro.h new file mode 100644 index 0000000000..56ee73e0d0 --- /dev/null +++ b/VUmicro.h @@ -0,0 +1,1263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUMICRO_H__ +#define __VUMICRO_H__ + +#include "VU.h" + +//both for VU0 VU1 micromode + +extern void (*VU0_LOWER_OPCODE[128])(); +extern void (*VU0_UPPER_OPCODE[64])(); + +extern void (*VU0_UPPER_FD_00_TABLE[32])(); +extern void (*VU0_UPPER_FD_01_TABLE[32])(); +extern void (*VU0_UPPER_FD_10_TABLE[32])(); +extern void (*VU0_UPPER_FD_11_TABLE[32])(); + +extern void (*VU0regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU0regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +extern void (*VU1_LOWER_OPCODE[128])(); +extern void (*VU1_UPPER_OPCODE[64])(); + +extern void (*VU1_UPPER_FD_00_TABLE[32])(); +extern void (*VU1_UPPER_FD_01_TABLE[32])(); +extern void (*VU1_UPPER_FD_10_TABLE[32])(); +extern void (*VU1_UPPER_FD_11_TABLE[32])(); + +extern void (*VU1regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU1regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +// VU0 +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); +void vu0ExecMicro(u32 addr); +void vu0Exec(VURegs* VU); +void vu0Finish(); +void recResetVU0( void ); + +// VU1 +int vu1Init(); +void vu1Reset(); +void vu1ResetRegs(); +void recResetVU1( void ); +void vu1Freeze(gzFile f, int Mode); +void vu1Shutdown(); +void vu1ExecMicro(u32 addr); +void vu1Exec(VURegs* VU); + +void VU0_UPPER_FD_00(); +void VU0_UPPER_FD_01(); +void VU0_UPPER_FD_10(); +void VU0_UPPER_FD_11(); + +void VU0LowerOP(); +void VU0LowerOP_T3_00(); +void VU0LowerOP_T3_01(); +void VU0LowerOP_T3_10(); +void VU0LowerOP_T3_11(); + +void VU0unknown(); + +void VU1_UPPER_FD_00(); +void VU1_UPPER_FD_01(); +void VU1_UPPER_FD_10(); +void VU1_UPPER_FD_11(); + +void VU1LowerOP(); +void VU1LowerOP_T3_00(); +void VU1LowerOP_T3_01(); +void VU1LowerOP_T3_10(); +void VU1LowerOP_T3_11(); + +void VU1unknown(); + +void VU0regs_UPPER_FD_00(); +void VU0regs_UPPER_FD_01(); +void VU0regs_UPPER_FD_10(); +void VU0regs_UPPER_FD_11(); + +void VU0regsLowerOP(); +void VU0regsLowerOP_T3_00(); +void VU0regsLowerOP_T3_01(); +void VU0regsLowerOP_T3_10(); +void VU0regsLowerOP_T3_11(); + +void VU0regsunknown(); + +void VU1regs_UPPER_FD_00(); +void VU1regs_UPPER_FD_01(); +void VU1regs_UPPER_FD_10(); +void VU1regs_UPPER_FD_11(); + +void VU1regsLowerOP(); +void VU1regsLowerOP_T3_00(); +void VU1regsLowerOP_T3_01(); +void VU1regsLowerOP_T3_10(); +void VU1regsLowerOP_T3_11(); + +void VU1regsunknown(); + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void VU0MI_ABS(); +void VU0MI_ADD(); +void VU0MI_ADDi(); +void VU0MI_ADDq(); +void VU0MI_ADDx(); +void VU0MI_ADDy(); +void VU0MI_ADDz(); +void VU0MI_ADDw(); +void VU0MI_ADDA(); +void VU0MI_ADDAi(); +void VU0MI_ADDAq(); +void VU0MI_ADDAx(); +void VU0MI_ADDAy(); +void VU0MI_ADDAz(); +void VU0MI_ADDAw(); +void VU0MI_SUB(); +void VU0MI_SUBi(); +void VU0MI_SUBq(); +void VU0MI_SUBx(); +void VU0MI_SUBy(); +void VU0MI_SUBz(); +void VU0MI_SUBw(); +void VU0MI_SUBA(); +void VU0MI_SUBAi(); +void VU0MI_SUBAq(); +void VU0MI_SUBAx(); +void VU0MI_SUBAy(); +void VU0MI_SUBAz(); +void VU0MI_SUBAw(); +void VU0MI_MUL(); +void VU0MI_MULi(); +void VU0MI_MULq(); +void VU0MI_MULx(); +void VU0MI_MULy(); +void VU0MI_MULz(); +void VU0MI_MULw(); +void VU0MI_MULA(); +void VU0MI_MULAi(); +void VU0MI_MULAq(); +void VU0MI_MULAx(); +void VU0MI_MULAy(); +void VU0MI_MULAz(); +void VU0MI_MULAw(); +void VU0MI_MADD(); +void VU0MI_MADDi(); +void VU0MI_MADDq(); +void VU0MI_MADDx(); +void VU0MI_MADDy(); +void VU0MI_MADDz(); +void VU0MI_MADDw(); +void VU0MI_MADDA(); +void VU0MI_MADDAi(); +void VU0MI_MADDAq(); +void VU0MI_MADDAx(); +void VU0MI_MADDAy(); +void VU0MI_MADDAz(); +void VU0MI_MADDAw(); +void VU0MI_MSUB(); +void VU0MI_MSUBi(); +void VU0MI_MSUBq(); +void VU0MI_MSUBx(); +void VU0MI_MSUBy(); +void VU0MI_MSUBz(); +void VU0MI_MSUBw(); +void VU0MI_MSUBA(); +void VU0MI_MSUBAi(); +void VU0MI_MSUBAq(); +void VU0MI_MSUBAx(); +void VU0MI_MSUBAy(); +void VU0MI_MSUBAz(); +void VU0MI_MSUBAw(); +void VU0MI_MAX(); +void VU0MI_MAXi(); +void VU0MI_MAXx(); +void VU0MI_MAXy(); +void VU0MI_MAXz(); +void VU0MI_MAXw(); +void VU0MI_MINI(); +void VU0MI_MINIi(); +void VU0MI_MINIx(); +void VU0MI_MINIy(); +void VU0MI_MINIz(); +void VU0MI_MINIw(); +void VU0MI_OPMULA(); +void VU0MI_OPMSUB(); +void VU0MI_NOP(); +void VU0MI_FTOI0(); +void VU0MI_FTOI4(); +void VU0MI_FTOI12(); +void VU0MI_FTOI15(); +void VU0MI_ITOF0(); +void VU0MI_ITOF4(); +void VU0MI_ITOF12(); +void VU0MI_ITOF15(); +void VU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0MI_DIV(); +void VU0MI_SQRT(); +void VU0MI_RSQRT(); +void VU0MI_IADD(); +void VU0MI_IADDI(); +void VU0MI_IADDIU(); +void VU0MI_IAND(); +void VU0MI_IOR(); +void VU0MI_ISUB(); +void VU0MI_ISUBIU(); +void VU0MI_MOVE(); +void VU0MI_MFIR(); +void VU0MI_MTIR(); +void VU0MI_MR32(); +void VU0MI_LQ(); +void VU0MI_LQD(); +void VU0MI_LQI(); +void VU0MI_SQ(); +void VU0MI_SQD(); +void VU0MI_SQI(); +void VU0MI_ILW(); +void VU0MI_ISW(); +void VU0MI_ILWR(); +void VU0MI_ISWR(); +void VU0MI_LOI(); +void VU0MI_RINIT(); +void VU0MI_RGET(); +void VU0MI_RNEXT(); +void VU0MI_RXOR(); +void VU0MI_WAITQ(); +void VU0MI_FSAND(); +void VU0MI_FSEQ(); +void VU0MI_FSOR(); +void VU0MI_FSSET(); +void VU0MI_FMAND(); +void VU0MI_FMEQ(); +void VU0MI_FMOR(); +void VU0MI_FCAND(); +void VU0MI_FCEQ(); +void VU0MI_FCOR(); +void VU0MI_FCSET(); +void VU0MI_FCGET(); +void VU0MI_IBEQ(); +void VU0MI_IBGEZ(); +void VU0MI_IBGTZ(); +void VU0MI_IBLEZ(); +void VU0MI_IBLTZ(); +void VU0MI_IBNE(); +void VU0MI_B(); +void VU0MI_BAL(); +void VU0MI_JR(); +void VU0MI_JALR(); +void VU0MI_MFP(); +void VU0MI_WAITP(); +void VU0MI_ESADD(); +void VU0MI_ERSADD(); +void VU0MI_ELENG(); +void VU0MI_ERLENG(); +void VU0MI_EATANxy(); +void VU0MI_EATANxz(); +void VU0MI_ESUM(); +void VU0MI_ERCPR(); +void VU0MI_ESQRT(); +void VU0MI_ERSQRT(); +void VU0MI_ESIN(); +void VU0MI_EATAN(); +void VU0MI_EEXP(); +void VU0MI_XGKICK(); +void VU0MI_XTOP(); +void VU0MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn); +void VU0regsMI_ADD(_VURegsNum *VUregsn); +void VU0regsMI_ADDi(_VURegsNum *VUregsn); +void VU0regsMI_ADDq(_VURegsNum *VUregsn); +void VU0regsMI_ADDx(_VURegsNum *VUregsn); +void VU0regsMI_ADDy(_VURegsNum *VUregsn); +void VU0regsMI_ADDz(_VURegsNum *VUregsn); +void VU0regsMI_ADDw(_VURegsNum *VUregsn); +void VU0regsMI_ADDA(_VURegsNum *VUregsn); +void VU0regsMI_ADDAi(_VURegsNum *VUregsn); +void VU0regsMI_ADDAq(_VURegsNum *VUregsn); +void VU0regsMI_ADDAx(_VURegsNum *VUregsn); +void VU0regsMI_ADDAy(_VURegsNum *VUregsn); +void VU0regsMI_ADDAz(_VURegsNum *VUregsn); +void VU0regsMI_ADDAw(_VURegsNum *VUregsn); +void VU0regsMI_SUB(_VURegsNum *VUregsn); +void VU0regsMI_SUBi(_VURegsNum *VUregsn); +void VU0regsMI_SUBq(_VURegsNum *VUregsn); +void VU0regsMI_SUBx(_VURegsNum *VUregsn); +void VU0regsMI_SUBy(_VURegsNum *VUregsn); +void VU0regsMI_SUBz(_VURegsNum *VUregsn); +void VU0regsMI_SUBw(_VURegsNum *VUregsn); +void VU0regsMI_SUBA(_VURegsNum *VUregsn); +void VU0regsMI_SUBAi(_VURegsNum *VUregsn); +void VU0regsMI_SUBAq(_VURegsNum *VUregsn); +void VU0regsMI_SUBAx(_VURegsNum *VUregsn); +void VU0regsMI_SUBAy(_VURegsNum *VUregsn); +void VU0regsMI_SUBAz(_VURegsNum *VUregsn); +void VU0regsMI_SUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MUL(_VURegsNum *VUregsn); +void VU0regsMI_MULi(_VURegsNum *VUregsn); +void VU0regsMI_MULq(_VURegsNum *VUregsn); +void VU0regsMI_MULx(_VURegsNum *VUregsn); +void VU0regsMI_MULy(_VURegsNum *VUregsn); +void VU0regsMI_MULz(_VURegsNum *VUregsn); +void VU0regsMI_MULw(_VURegsNum *VUregsn); +void VU0regsMI_MULA(_VURegsNum *VUregsn); +void VU0regsMI_MULAi(_VURegsNum *VUregsn); +void VU0regsMI_MULAq(_VURegsNum *VUregsn); +void VU0regsMI_MULAx(_VURegsNum *VUregsn); +void VU0regsMI_MULAy(_VURegsNum *VUregsn); +void VU0regsMI_MULAz(_VURegsNum *VUregsn); +void VU0regsMI_MULAw(_VURegsNum *VUregsn); +void VU0regsMI_MADD(_VURegsNum *VUregsn); +void VU0regsMI_MADDi(_VURegsNum *VUregsn); +void VU0regsMI_MADDq(_VURegsNum *VUregsn); +void VU0regsMI_MADDx(_VURegsNum *VUregsn); +void VU0regsMI_MADDy(_VURegsNum *VUregsn); +void VU0regsMI_MADDz(_VURegsNum *VUregsn); +void VU0regsMI_MADDw(_VURegsNum *VUregsn); +void VU0regsMI_MADDA(_VURegsNum *VUregsn); +void VU0regsMI_MADDAi(_VURegsNum *VUregsn); +void VU0regsMI_MADDAq(_VURegsNum *VUregsn); +void VU0regsMI_MADDAx(_VURegsNum *VUregsn); +void VU0regsMI_MADDAy(_VURegsNum *VUregsn); +void VU0regsMI_MADDAz(_VURegsNum *VUregsn); +void VU0regsMI_MADDAw(_VURegsNum *VUregsn); +void VU0regsMI_MSUB(_VURegsNum *VUregsn); +void VU0regsMI_MSUBi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBw(_VURegsNum *VUregsn); +void VU0regsMI_MSUBA(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MAX(_VURegsNum *VUregsn); +void VU0regsMI_MAXi(_VURegsNum *VUregsn); +void VU0regsMI_MAXx(_VURegsNum *VUregsn); +void VU0regsMI_MAXy(_VURegsNum *VUregsn); +void VU0regsMI_MAXz(_VURegsNum *VUregsn); +void VU0regsMI_MAXw(_VURegsNum *VUregsn); +void VU0regsMI_MINI(_VURegsNum *VUregsn); +void VU0regsMI_MINIi(_VURegsNum *VUregsn); +void VU0regsMI_MINIx(_VURegsNum *VUregsn); +void VU0regsMI_MINIy(_VURegsNum *VUregsn); +void VU0regsMI_MINIz(_VURegsNum *VUregsn); +void VU0regsMI_MINIw(_VURegsNum *VUregsn); +void VU0regsMI_OPMULA(_VURegsNum *VUregsn); +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU0regsMI_NOP(_VURegsNum *VUregsn); +void VU0regsMI_FTOI0(_VURegsNum *VUregsn); +void VU0regsMI_FTOI4(_VURegsNum *VUregsn); +void VU0regsMI_FTOI12(_VURegsNum *VUregsn); +void VU0regsMI_FTOI15(_VURegsNum *VUregsn); +void VU0regsMI_ITOF0(_VURegsNum *VUregsn); +void VU0regsMI_ITOF4(_VURegsNum *VUregsn); +void VU0regsMI_ITOF12(_VURegsNum *VUregsn); +void VU0regsMI_ITOF15(_VURegsNum *VUregsn); +void VU0regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn); +void VU0regsMI_SQRT(_VURegsNum *VUregsn); +void VU0regsMI_RSQRT(_VURegsNum *VUregsn); +void VU0regsMI_IADD(_VURegsNum *VUregsn); +void VU0regsMI_IADDI(_VURegsNum *VUregsn); +void VU0regsMI_IADDIU(_VURegsNum *VUregsn); +void VU0regsMI_IAND(_VURegsNum *VUregsn); +void VU0regsMI_IOR(_VURegsNum *VUregsn); +void VU0regsMI_ISUB(_VURegsNum *VUregsn); +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU0regsMI_MOVE(_VURegsNum *VUregsn); +void VU0regsMI_MFIR(_VURegsNum *VUregsn); +void VU0regsMI_MTIR(_VURegsNum *VUregsn); +void VU0regsMI_MR32(_VURegsNum *VUregsn); +void VU0regsMI_LQ(_VURegsNum *VUregsn); +void VU0regsMI_LQD(_VURegsNum *VUregsn); +void VU0regsMI_LQI(_VURegsNum *VUregsn); +void VU0regsMI_SQ(_VURegsNum *VUregsn); +void VU0regsMI_SQD(_VURegsNum *VUregsn); +void VU0regsMI_SQI(_VURegsNum *VUregsn); +void VU0regsMI_ILW(_VURegsNum *VUregsn); +void VU0regsMI_ISW(_VURegsNum *VUregsn); +void VU0regsMI_ILWR(_VURegsNum *VUregsn); +void VU0regsMI_ISWR(_VURegsNum *VUregsn); +void VU0regsMI_LOI(_VURegsNum *VUregsn); +void VU0regsMI_RINIT(_VURegsNum *VUregsn); +void VU0regsMI_RGET(_VURegsNum *VUregsn); +void VU0regsMI_RNEXT(_VURegsNum *VUregsn); +void VU0regsMI_RXOR(_VURegsNum *VUregsn); +void VU0regsMI_WAITQ(_VURegsNum *VUregsn); +void VU0regsMI_FSAND(_VURegsNum *VUregsn); +void VU0regsMI_FSEQ(_VURegsNum *VUregsn); +void VU0regsMI_FSOR(_VURegsNum *VUregsn); +void VU0regsMI_FSSET(_VURegsNum *VUregsn); +void VU0regsMI_FMAND(_VURegsNum *VUregsn); +void VU0regsMI_FMEQ(_VURegsNum *VUregsn); +void VU0regsMI_FMOR(_VURegsNum *VUregsn); +void VU0regsMI_FCAND(_VURegsNum *VUregsn); +void VU0regsMI_FCEQ(_VURegsNum *VUregsn); +void VU0regsMI_FCOR(_VURegsNum *VUregsn); +void VU0regsMI_FCSET(_VURegsNum *VUregsn); +void VU0regsMI_FCGET(_VURegsNum *VUregsn); +void VU0regsMI_IBEQ(_VURegsNum *VUregsn); +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBNE(_VURegsNum *VUregsn); +void VU0regsMI_B(_VURegsNum *VUregsn); +void VU0regsMI_BAL(_VURegsNum *VUregsn); +void VU0regsMI_JR(_VURegsNum *VUregsn); +void VU0regsMI_JALR(_VURegsNum *VUregsn); +void VU0regsMI_MFP(_VURegsNum *VUregsn); +void VU0regsMI_WAITP(_VURegsNum *VUregsn); +void VU0regsMI_ESADD(_VURegsNum *VUregsn); +void VU0regsMI_ERSADD(_VURegsNum *VUregsn); +void VU0regsMI_ELENG(_VURegsNum *VUregsn); +void VU0regsMI_ERLENG(_VURegsNum *VUregsn); +void VU0regsMI_EATANxy(_VURegsNum *VUregsn); +void VU0regsMI_EATANxz(_VURegsNum *VUregsn); +void VU0regsMI_ESUM(_VURegsNum *VUregsn); +void VU0regsMI_ERCPR(_VURegsNum *VUregsn); +void VU0regsMI_ESQRT(_VURegsNum *VUregsn); +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU0regsMI_ESIN(_VURegsNum *VUregsn); +void VU0regsMI_EATAN(_VURegsNum *VUregsn); +void VU0regsMI_EEXP(_VURegsNum *VUregsn); +void VU0regsMI_XGKICK(_VURegsNum *VUregsn); +void VU0regsMI_XTOP(_VURegsNum *VUregsn); +void VU0regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1MI_ABS(); +void VU1MI_ADD(); +void VU1MI_ADDi(); +void VU1MI_ADDq(); +void VU1MI_ADDx(); +void VU1MI_ADDy(); +void VU1MI_ADDz(); +void VU1MI_ADDw(); +void VU1MI_ADDA(); +void VU1MI_ADDAi(); +void VU1MI_ADDAq(); +void VU1MI_ADDAx(); +void VU1MI_ADDAy(); +void VU1MI_ADDAz(); +void VU1MI_ADDAw(); +void VU1MI_SUB(); +void VU1MI_SUBi(); +void VU1MI_SUBq(); +void VU1MI_SUBx(); +void VU1MI_SUBy(); +void VU1MI_SUBz(); +void VU1MI_SUBw(); +void VU1MI_SUBA(); +void VU1MI_SUBAi(); +void VU1MI_SUBAq(); +void VU1MI_SUBAx(); +void VU1MI_SUBAy(); +void VU1MI_SUBAz(); +void VU1MI_SUBAw(); +void VU1MI_MUL(); +void VU1MI_MULi(); +void VU1MI_MULq(); +void VU1MI_MULx(); +void VU1MI_MULy(); +void VU1MI_MULz(); +void VU1MI_MULw(); +void VU1MI_MULA(); +void VU1MI_MULAi(); +void VU1MI_MULAq(); +void VU1MI_MULAx(); +void VU1MI_MULAy(); +void VU1MI_MULAz(); +void VU1MI_MULAw(); +void VU1MI_MADD(); +void VU1MI_MADDi(); +void VU1MI_MADDq(); +void VU1MI_MADDx(); +void VU1MI_MADDy(); +void VU1MI_MADDz(); +void VU1MI_MADDw(); +void VU1MI_MADDA(); +void VU1MI_MADDAi(); +void VU1MI_MADDAq(); +void VU1MI_MADDAx(); +void VU1MI_MADDAy(); +void VU1MI_MADDAz(); +void VU1MI_MADDAw(); +void VU1MI_MSUB(); +void VU1MI_MSUBi(); +void VU1MI_MSUBq(); +void VU1MI_MSUBx(); +void VU1MI_MSUBy(); +void VU1MI_MSUBz(); +void VU1MI_MSUBw(); +void VU1MI_MSUBA(); +void VU1MI_MSUBAi(); +void VU1MI_MSUBAq(); +void VU1MI_MSUBAx(); +void VU1MI_MSUBAy(); +void VU1MI_MSUBAz(); +void VU1MI_MSUBAw(); +void VU1MI_MAX(); +void VU1MI_MAXi(); +void VU1MI_MAXx(); +void VU1MI_MAXy(); +void VU1MI_MAXz(); +void VU1MI_MAXw(); +void VU1MI_MINI(); +void VU1MI_MINIi(); +void VU1MI_MINIx(); +void VU1MI_MINIy(); +void VU1MI_MINIz(); +void VU1MI_MINIw(); +void VU1MI_OPMULA(); +void VU1MI_OPMSUB(); +void VU1MI_NOP(); +void VU1MI_FTOI0(); +void VU1MI_FTOI4(); +void VU1MI_FTOI12(); +void VU1MI_FTOI15(); +void VU1MI_ITOF0(); +void VU1MI_ITOF4(); +void VU1MI_ITOF12(); +void VU1MI_ITOF15(); +void VU1MI_CLIP(); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1MI_DIV(); +void VU1MI_SQRT(); +void VU1MI_RSQRT(); +void VU1MI_IADD(); +void VU1MI_IADDI(); +void VU1MI_IADDIU(); +void VU1MI_IAND(); +void VU1MI_IOR(); +void VU1MI_ISUB(); +void VU1MI_ISUBIU(); +void VU1MI_MOVE(); +void VU1MI_MFIR(); +void VU1MI_MTIR(); +void VU1MI_MR32(); +void VU1MI_LQ(); +void VU1MI_LQD(); +void VU1MI_LQI(); +void VU1MI_SQ(); +void VU1MI_SQD(); +void VU1MI_SQI(); +void VU1MI_ILW(); +void VU1MI_ISW(); +void VU1MI_ILWR(); +void VU1MI_ISWR(); +void VU1MI_LOI(); +void VU1MI_RINIT(); +void VU1MI_RGET(); +void VU1MI_RNEXT(); +void VU1MI_RXOR(); +void VU1MI_WAITQ(); +void VU1MI_FSAND(); +void VU1MI_FSEQ(); +void VU1MI_FSOR(); +void VU1MI_FSSET(); +void VU1MI_FMAND(); +void VU1MI_FMEQ(); +void VU1MI_FMOR(); +void VU1MI_FCAND(); +void VU1MI_FCEQ(); +void VU1MI_FCOR(); +void VU1MI_FCSET(); +void VU1MI_FCGET(); +void VU1MI_IBEQ(); +void VU1MI_IBGEZ(); +void VU1MI_IBGTZ(); +void VU1MI_IBLTZ(); +void VU1MI_IBLEZ(); +void VU1MI_IBNE(); +void VU1MI_B(); +void VU1MI_BAL(); +void VU1MI_JR(); +void VU1MI_JALR(); +void VU1MI_MFP(); +void VU1MI_WAITP(); +void VU1MI_ESADD(); +void VU1MI_ERSADD(); +void VU1MI_ELENG(); +void VU1MI_ERLENG(); +void VU1MI_EATANxy(); +void VU1MI_EATANxz(); +void VU1MI_ESUM(); +void VU1MI_ERCPR(); +void VU1MI_ESQRT(); +void VU1MI_ERSQRT(); +void VU1MI_ESIN(); +void VU1MI_EATAN(); +void VU1MI_EEXP(); +void VU1MI_XGKICK(); +void VU1MI_XTOP(); +void VU1MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn); +void VU1regsMI_ADD(_VURegsNum *VUregsn); +void VU1regsMI_ADDi(_VURegsNum *VUregsn); +void VU1regsMI_ADDq(_VURegsNum *VUregsn); +void VU1regsMI_ADDx(_VURegsNum *VUregsn); +void VU1regsMI_ADDy(_VURegsNum *VUregsn); +void VU1regsMI_ADDz(_VURegsNum *VUregsn); +void VU1regsMI_ADDw(_VURegsNum *VUregsn); +void VU1regsMI_ADDA(_VURegsNum *VUregsn); +void VU1regsMI_ADDAi(_VURegsNum *VUregsn); +void VU1regsMI_ADDAq(_VURegsNum *VUregsn); +void VU1regsMI_ADDAx(_VURegsNum *VUregsn); +void VU1regsMI_ADDAy(_VURegsNum *VUregsn); +void VU1regsMI_ADDAz(_VURegsNum *VUregsn); +void VU1regsMI_ADDAw(_VURegsNum *VUregsn); +void VU1regsMI_SUB(_VURegsNum *VUregsn); +void VU1regsMI_SUBi(_VURegsNum *VUregsn); +void VU1regsMI_SUBq(_VURegsNum *VUregsn); +void VU1regsMI_SUBx(_VURegsNum *VUregsn); +void VU1regsMI_SUBy(_VURegsNum *VUregsn); +void VU1regsMI_SUBz(_VURegsNum *VUregsn); +void VU1regsMI_SUBw(_VURegsNum *VUregsn); +void VU1regsMI_SUBA(_VURegsNum *VUregsn); +void VU1regsMI_SUBAi(_VURegsNum *VUregsn); +void VU1regsMI_SUBAq(_VURegsNum *VUregsn); +void VU1regsMI_SUBAx(_VURegsNum *VUregsn); +void VU1regsMI_SUBAy(_VURegsNum *VUregsn); +void VU1regsMI_SUBAz(_VURegsNum *VUregsn); +void VU1regsMI_SUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MUL(_VURegsNum *VUregsn); +void VU1regsMI_MULi(_VURegsNum *VUregsn); +void VU1regsMI_MULq(_VURegsNum *VUregsn); +void VU1regsMI_MULx(_VURegsNum *VUregsn); +void VU1regsMI_MULy(_VURegsNum *VUregsn); +void VU1regsMI_MULz(_VURegsNum *VUregsn); +void VU1regsMI_MULw(_VURegsNum *VUregsn); +void VU1regsMI_MULA(_VURegsNum *VUregsn); +void VU1regsMI_MULAi(_VURegsNum *VUregsn); +void VU1regsMI_MULAq(_VURegsNum *VUregsn); +void VU1regsMI_MULAx(_VURegsNum *VUregsn); +void VU1regsMI_MULAy(_VURegsNum *VUregsn); +void VU1regsMI_MULAz(_VURegsNum *VUregsn); +void VU1regsMI_MULAw(_VURegsNum *VUregsn); +void VU1regsMI_MADD(_VURegsNum *VUregsn); +void VU1regsMI_MADDi(_VURegsNum *VUregsn); +void VU1regsMI_MADDq(_VURegsNum *VUregsn); +void VU1regsMI_MADDx(_VURegsNum *VUregsn); +void VU1regsMI_MADDy(_VURegsNum *VUregsn); +void VU1regsMI_MADDz(_VURegsNum *VUregsn); +void VU1regsMI_MADDw(_VURegsNum *VUregsn); +void VU1regsMI_MADDA(_VURegsNum *VUregsn); +void VU1regsMI_MADDAi(_VURegsNum *VUregsn); +void VU1regsMI_MADDAq(_VURegsNum *VUregsn); +void VU1regsMI_MADDAx(_VURegsNum *VUregsn); +void VU1regsMI_MADDAy(_VURegsNum *VUregsn); +void VU1regsMI_MADDAz(_VURegsNum *VUregsn); +void VU1regsMI_MADDAw(_VURegsNum *VUregsn); +void VU1regsMI_MSUB(_VURegsNum *VUregsn); +void VU1regsMI_MSUBi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBw(_VURegsNum *VUregsn); +void VU1regsMI_MSUBA(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MAX(_VURegsNum *VUregsn); +void VU1regsMI_MAXi(_VURegsNum *VUregsn); +void VU1regsMI_MAXx(_VURegsNum *VUregsn); +void VU1regsMI_MAXy(_VURegsNum *VUregsn); +void VU1regsMI_MAXz(_VURegsNum *VUregsn); +void VU1regsMI_MAXw(_VURegsNum *VUregsn); +void VU1regsMI_MINI(_VURegsNum *VUregsn); +void VU1regsMI_MINIi(_VURegsNum *VUregsn); +void VU1regsMI_MINIx(_VURegsNum *VUregsn); +void VU1regsMI_MINIy(_VURegsNum *VUregsn); +void VU1regsMI_MINIz(_VURegsNum *VUregsn); +void VU1regsMI_MINIw(_VURegsNum *VUregsn); +void VU1regsMI_OPMULA(_VURegsNum *VUregsn); +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU1regsMI_NOP(_VURegsNum *VUregsn); +void VU1regsMI_FTOI0(_VURegsNum *VUregsn); +void VU1regsMI_FTOI4(_VURegsNum *VUregsn); +void VU1regsMI_FTOI12(_VURegsNum *VUregsn); +void VU1regsMI_FTOI15(_VURegsNum *VUregsn); +void VU1regsMI_ITOF0(_VURegsNum *VUregsn); +void VU1regsMI_ITOF4(_VURegsNum *VUregsn); +void VU1regsMI_ITOF12(_VURegsNum *VUregsn); +void VU1regsMI_ITOF15(_VURegsNum *VUregsn); +void VU1regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn); +void VU1regsMI_SQRT(_VURegsNum *VUregsn); +void VU1regsMI_RSQRT(_VURegsNum *VUregsn); +void VU1regsMI_IADD(_VURegsNum *VUregsn); +void VU1regsMI_IADDI(_VURegsNum *VUregsn); +void VU1regsMI_IADDIU(_VURegsNum *VUregsn); +void VU1regsMI_IAND(_VURegsNum *VUregsn); +void VU1regsMI_IOR(_VURegsNum *VUregsn); +void VU1regsMI_ISUB(_VURegsNum *VUregsn); +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU1regsMI_MOVE(_VURegsNum *VUregsn); +void VU1regsMI_MFIR(_VURegsNum *VUregsn); +void VU1regsMI_MTIR(_VURegsNum *VUregsn); +void VU1regsMI_MR32(_VURegsNum *VUregsn); +void VU1regsMI_LQ(_VURegsNum *VUregsn); +void VU1regsMI_LQD(_VURegsNum *VUregsn); +void VU1regsMI_LQI(_VURegsNum *VUregsn); +void VU1regsMI_SQ(_VURegsNum *VUregsn); +void VU1regsMI_SQD(_VURegsNum *VUregsn); +void VU1regsMI_SQI(_VURegsNum *VUregsn); +void VU1regsMI_ILW(_VURegsNum *VUregsn); +void VU1regsMI_ISW(_VURegsNum *VUregsn); +void VU1regsMI_ILWR(_VURegsNum *VUregsn); +void VU1regsMI_ISWR(_VURegsNum *VUregsn); +void VU1regsMI_LOI(_VURegsNum *VUregsn); +void VU1regsMI_RINIT(_VURegsNum *VUregsn); +void VU1regsMI_RGET(_VURegsNum *VUregsn); +void VU1regsMI_RNEXT(_VURegsNum *VUregsn); +void VU1regsMI_RXOR(_VURegsNum *VUregsn); +void VU1regsMI_WAITQ(_VURegsNum *VUregsn); +void VU1regsMI_FSAND(_VURegsNum *VUregsn); +void VU1regsMI_FSEQ(_VURegsNum *VUregsn); +void VU1regsMI_FSOR(_VURegsNum *VUregsn); +void VU1regsMI_FSSET(_VURegsNum *VUregsn); +void VU1regsMI_FMAND(_VURegsNum *VUregsn); +void VU1regsMI_FMEQ(_VURegsNum *VUregsn); +void VU1regsMI_FMOR(_VURegsNum *VUregsn); +void VU1regsMI_FCAND(_VURegsNum *VUregsn); +void VU1regsMI_FCEQ(_VURegsNum *VUregsn); +void VU1regsMI_FCOR(_VURegsNum *VUregsn); +void VU1regsMI_FCSET(_VURegsNum *VUregsn); +void VU1regsMI_FCGET(_VURegsNum *VUregsn); +void VU1regsMI_IBEQ(_VURegsNum *VUregsn); +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBNE(_VURegsNum *VUregsn); +void VU1regsMI_B(_VURegsNum *VUregsn); +void VU1regsMI_BAL(_VURegsNum *VUregsn); +void VU1regsMI_JR(_VURegsNum *VUregsn); +void VU1regsMI_JALR(_VURegsNum *VUregsn); +void VU1regsMI_MFP(_VURegsNum *VUregsn); +void VU1regsMI_WAITP(_VURegsNum *VUregsn); +void VU1regsMI_ESADD(_VURegsNum *VUregsn); +void VU1regsMI_ERSADD(_VURegsNum *VUregsn); +void VU1regsMI_ELENG(_VURegsNum *VUregsn); +void VU1regsMI_ERLENG(_VURegsNum *VUregsn); +void VU1regsMI_EATANxy(_VURegsNum *VUregsn); +void VU1regsMI_EATANxz(_VURegsNum *VUregsn); +void VU1regsMI_ESUM(_VURegsNum *VUregsn); +void VU1regsMI_ERCPR(_VURegsNum *VUregsn); +void VU1regsMI_ESQRT(_VURegsNum *VUregsn); +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU1regsMI_ESIN(_VURegsNum *VUregsn); +void VU1regsMI_EATAN(_VURegsNum *VUregsn); +void VU1regsMI_EEXP(_VURegsNum *VUregsn); +void VU1regsMI_XGKICK(_VURegsNum *VUregsn); +void VU1regsMI_XTOP(_VURegsNum *VUregsn); +void VU1regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU Micromode Tables/Opcodes defs macros +*****************************************/ + + +#define _vuTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])() = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])() = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])() = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])() = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])() = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_MADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])() = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00() { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](); \ +} \ + \ + void PREFIX##_UPPER_FD_01() { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_10() { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_11() { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP() { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](); \ +} \ + \ + void PREFIX##LowerOP_T3_00() { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_01() { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_10() { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_11() { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](); \ +} + +#define _vuRegsTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_MADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_01(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_10(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_11(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_00(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_01(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_10(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_11(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} + + +#ifdef VUM_LOG + +#define IdebugUPPER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroUF(VU.code, VU.VI[REG_TPC].UL)); } +#define IdebugLOWER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroLF(VU.code, VU.VI[REG_TPC].UL)); } + +#else + +#define IdebugUPPER(VU) +#define IdebugLOWER(VU) + +#endif + +#ifdef VUM_LOG +#define _vuExecMicroDebug(VU) \ + VUM_LOG("_vuExecMicro: %8.8x\n", VU.VI[REG_TPC].UL); +#else +#define _vuExecMicroDebug(VU) +#endif + +#include "VUops.h" + +#endif + diff --git a/VUops.c b/VUops.c new file mode 100644 index 0000000000..3e29ef0a03 --- /dev/null +++ b/VUops.c @@ -0,0 +1,2945 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU->code>>24) & 0x1) +#define _Y ((VU->code>>23) & 0x1) +#define _Z ((VU->code>>22) & 0x1) +#define _W ((VU->code>>21) & 0x1) + +#define _XYZW ((VU->code>>21) & 0xF) + +#define _Fsf_ ((VU->code >> 21) & 0x03) +#define _Ftf_ ((VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + + +VECTOR RDzero; + +void _vuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } +} + +void _vuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } +#endif + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } +} + +void _vuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing EFU pipe\n"); } +#endif + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } +} + +// called at end of program +void _vuFlushAll(VURegs* VU) +{ + int nRepeat = 1, i; + + do { + nRepeat = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + nRepeat = 1; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } + + if (VU->fdiv.enable ) { + + nRepeat = 1; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { + #ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } + #endif + nRepeat = 1; + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } + } + + if (VU->efu.enable) { + + nRepeat = 1; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { + #ifdef VUM_LOG + // if (Log) { VUM_LOG("flushing EFU pipe\n"); } + #endif + nRepeat = 1; + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } + } + + VU->cycle++; + + } while(nRepeat); +} + +void _vuTestPipes(VURegs * VU) { + _vuFMACflush(VU); + _vuFDIVflush(VU); + _vuEFUflush(VU); +} + +void _vuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + VU->fmac[i].xyzw & xyzw) break; + } + + if (i == 8) return; + + cycle = VU->fmac[i].Cycle - (VU->cycle - VU->fmac[i].sCycle) + 1; // add 1 delay! (fixes segaclassics bad geom) + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; +#ifdef VUM_LOG + if (Log) { VUM_LOG("FMAC[%d] stall %d\n", i, cycle); } +#endif + VU->cycle+= cycle; + _vuTestPipes(VU); +} + +void _vuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { +// SysPrintf("*PCSX2*: error , out of fmacs %d\n", VU->cycle); + } + +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FMAC pipe[%d]; xyzw=%x\n", i, xyzw); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = VU->cycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].reg = reg; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].macflag = VU->macflag; + VU->fmac[i].statusflag = VU->statusflag; + VU->fmac[i].clipflag = VU->clipflag; +} + +void _vuFDIVAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FDIV pipe\n"); } +#endif + VU->fdiv.enable = 1; + VU->fdiv.sCycle = VU->cycle; + VU->fdiv.Cycle = cycles; + VU->fdiv.reg.F = VU->q.F; + VU->fdiv.statusflag = VU->statusflag; +} + +void _vuEFUAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding EFU pipe\n"); } +#endif + VU->efu.enable = 1; + VU->efu.sCycle = VU->cycle; + VU->efu.Cycle = cycles; + VU->efu.reg.F = VU->p.F; +} + +void _vuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (VU->cycle - VU->fdiv.sCycle); +#ifdef VUM_LOG + if (Log) { VUM_LOG("waiting FDIV pipe %d\n", cycle); } +#endif + VU->fdiv.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; +} + +void _vuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (VU->cycle - VU->efu.sCycle); +#ifdef VUM_LOG +// if (Log) { VUM_LOG("waiting EFU pipe %d\n", cycle); } +#endif + VU->efu.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_P].UL = VU->efu.reg.UL; +} + +void _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFread0) { + _vuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _vuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } +} + +void _vuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _vuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { + _vuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _vuFMACAdd(VU, 0, 0); + } +} + +void _vuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushFDIV(VU); +} + +void _vuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_Q)) { + _vuFDIVAdd(VU, VUregsn->cycles); + } +} + + +void _vuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushEFU(VU); +} + +void _vuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_P)) { + _vuEFUAdd(VU, VUregsn->cycles); + } +} + +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + } +} + +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuTestEFUStalls(VU, VUregsn); break; + } +} + +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + } +} + +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuAddEFUStalls(VU, VUregsn); break; + } +} + + +/******************************/ +/* VU Upper instructions */ +/******************************/ +static u32 d; + +static float vuDouble(u32 f) +{ + switch(f & 0x7f800000){ + case 0x0: + f &= 0x80000000; + return *(float*)&f; + break; + case 0x7f800000: + d = (f & 0x80000000)|0x7f7fffff; + return *(float*)&d; + break; + default: + return *(float*)&f; + break; + } +} + +void _vuABS(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X){ VU->VF[_Ft_].f.x = fpufabsf(vuDouble(VU->VF[_Fs_].i.x)); } + if (_Y){ VU->VF[_Ft_].f.y = fpufabsf(vuDouble(VU->VF[_Fs_].i.y)); } + if (_Z){ VU->VF[_Ft_].f.z = fpufabsf(vuDouble(VU->VF[_Fs_].i.z)); } + if (_W){ VU->VF[_Ft_].f.w = fpufabsf(vuDouble(VU->VF[_Fs_].i.w)); } +}/*Reworked from define to function. asadr*/ + + +void _vuADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_I].UL));} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_I].UL));} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_I].UL));} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_I].UL));} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + fty);} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + fty);} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + fty);} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + fty);} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ti); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ti); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ti); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ti); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAq(VURegs * VU) { + float tf = vuDouble(VU->VI[REG_Q].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tf); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tf); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tf); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tf); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + + +void _vuSUBA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuMUL(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave Q reg in ti. asadr */ +void _vuMULAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave X reg in ti. asadr */ +void _vuMULAx(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAy(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAz(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAw(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + + +void _vuMADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +/* No need to presave . asadr */ +void _vuMADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftx)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftx)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftx)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * fty)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * fty)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * fty)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * fty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftz)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftz)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftz)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftw)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftw)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftw)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * ti)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * ti)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * ti)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * ti)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * tq)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * tq)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * tq)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * tq)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 10/05/03 shadow*/ + +void _vuMADDAx(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAy(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAz(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAw(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ti ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ti ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ti ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ti ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tq ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tq ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tq ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tq ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftx ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftx ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftx ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftx ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * fty ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * fty ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * fty ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * fty ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftz ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftz ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftz ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftz ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftw ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftw ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftw ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftw ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAi(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAq(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tx)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tx)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tx)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ty)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ty)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ty)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tz)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tz)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tz)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tw)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tw)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tw)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +u32 _MAX(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? b : a; + } else { // +b + return b; + } + } else { // +a + if (b & 0x80000000) { // -b + return a; + } else { // +b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMAX(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMAXi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMAXx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMAXy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMAXz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMAXw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftw); +} + +u32 _MINI(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? b : a; + } else { // +b + return a; + } + } else { // +a + if (b & 0x80000000) { // -b + return b; + } else { // +b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMINI(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMINIi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMINIx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMINIy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMINIz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMINIw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftw); +} + +void _vuOPMULA(VURegs * VU) { + VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); + VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); + VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuOPMSUB(VURegs * VU) { + VECTOR * dst; + float ftx, fty, ftz; + float fsx, fsy, fsz; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx = vuDouble(VU->VF[_Ft_].i.x); fty = vuDouble(VU->VF[_Ft_].i.y); ftz = vuDouble(VU->VF[_Ft_].i.z); + fsx = vuDouble(VU->VF[_Fs_].i.x); fsy = vuDouble(VU->VF[_Fs_].i.y); fsz = vuDouble(VU->VF[_Fs_].i.z); + dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - fsy * ftz); + dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - fsz * ftx); + dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - fsx * fty); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuNOP(VURegs * VU) { +} + +void _vuFTOI0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)vuDouble(VU->VF[_Fs_].i.x); + if (_Y) VU->VF[_Ft_].SL[1] = (s32)vuDouble(VU->VF[_Fs_].i.y); + if (_Z) VU->VF[_Ft_].SL[2] = (s32)vuDouble(VU->VF[_Fs_].i.z); + if (_W) VU->VF[_Ft_].SL[3] = (s32)vuDouble(VU->VF[_Fs_].i.w); +} + +void _vuFTOI4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int4(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int4(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int4(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int4(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int12(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int12(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int12(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int12(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int15(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int15(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int15(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int15(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuITOF0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = (float)VU->VF[_Fs_].SL[0]; + if (_Y) VU->VF[_Ft_].f.y = (float)VU->VF[_Fs_].SL[1]; + if (_Z) VU->VF[_Ft_].f.z = (float)VU->VF[_Fs_].SL[2]; + if (_W) VU->VF[_Ft_].f.w = (float)VU->VF[_Fs_].SL[3]; +} + +void _vuITOF4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int4_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int4_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int4_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int4_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int12_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int12_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int12_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int12_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int15_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int15_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int15_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int15_to_float(VU->VF[_Fs_].SL[3]); +} + +/* Different type of clipping by presaving w. asadr */ +void _vuCLIP(VURegs * VU) { + float value = fpufabsf(vuDouble(VU->VF[_Ft_].i.w)); + + VU->clipflag <<= 6; + if ( vuDouble(VU->VF[_Fs_].i.x) > +value ) VU->clipflag|= 0x01; + if ( vuDouble(VU->VF[_Fs_].i.x) < -value ) VU->clipflag|= 0x02; + if ( vuDouble(VU->VF[_Fs_].i.y) > +value ) VU->clipflag|= 0x04; + if ( vuDouble(VU->VF[_Fs_].i.y) < -value ) VU->clipflag|= 0x08; + if ( vuDouble(VU->VF[_Fs_].i.z) > +value ) VU->clipflag|= 0x10; + if ( vuDouble(VU->VF[_Fs_].i.z) < -value ) VU->clipflag|= 0x20; + VU->clipflag = VU->clipflag & 0xFFFFFF; + VU->VI[REG_CLIP_FLAG].UL = VU->clipflag; + + +}/*last update 16/07/05 refraction - Needs checking */ + + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuDIV(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft == 0.0) { + if (fs == 0.0) { + VU->statusflag |= 0x10; + } else { + VU->statusflag |= 0x20; + } + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } else { + VU->q.F = fs / ft; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + +void _vuSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + +// _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft < 0.0 ) + VU->statusflag |= 0x10; + VU->q.F = fpusqrtf(fpufabsf(ft)); + VU->q.F = vuDouble(VU->q.UL); +} //last update 15/01/06 zerofrog + + +/* Eminent Bug - Dvisior == 0 Check Missing ( D Flag Not Set ) */ +/* REFIXED....ASADR; rerefixed....zerofrog */ +void _vuRSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + float temp; + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if ( ft == 0.0 ) { + VU->statusflag |= 0x20; + + if( fs != 0 ) { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } + else { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0x80000000; + } else { + VU->q.UL = 0; + } + + VU->statusflag |= 0x10; + } + + } else { + if (ft < 0.0) { + VU->statusflag |= 0x10; + } + + temp = fpusqrtf(fpufabsf(ft)); + VU->q.F = fs / temp; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + + +void _vuIADDI(VURegs * VU) { + s16 imm = ((VU->code >> 6) & 0x1f); + imm = ((imm & 0x10 ? 0xfff0 : 0) | (imm & 0xf)); + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + imm; +}//last checked 17/05/03 shadow NOTE: not quite sure about that + +void _vuIADDIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +}//last checked 17/05/03 shadow + +void _vuIADD(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] + VU->VI[_Ft_].SS[0]; +}//last checked 17/05/03 shadow + +void _vuIAND(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] & VU->VI[_Ft_].US[0]; +}//last checked 17/05/03 shadow + +void _vuIOR(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] | VU->VI[_Ft_].US[0]; +} + +void _vuISUB(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] - VU->VI[_Ft_].SS[0]; +} + +void _vuISUBIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] - (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +} + +void _vuMOVE(VURegs * VU) { + if(_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VF[_Fs_].UL[0]; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VF[_Fs_].UL[1]; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VF[_Fs_].UL[2]; + if (_W) VU->VF[_Ft_].UL[3] = VU->VF[_Fs_].UL[3]; +}//last checked 17/05/03 shadow + +void _vuMFIR(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)VU->VI[_Fs_].SS[0]; + if (_Y) VU->VF[_Ft_].SL[1] = (s32)VU->VI[_Fs_].SS[0]; + if (_Z) VU->VF[_Ft_].SL[2] = (s32)VU->VI[_Fs_].SS[0]; + if (_W) VU->VF[_Ft_].SL[3] = (s32)VU->VI[_Fs_].SS[0]; +} + +// Big bug!!! mov from fs to ft not ft to fs. asadr +void _vuMTIR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = *(u16*)&VU->VF[_Fs_].F[_Fsf_]; +} + +void _vuMR32(VURegs * VU) { + u32 tx; + if (_Ft_ == 0) return; + + tx = VU->VF[_Fs_].i.x; + if (_X) VU->VF[_Ft_].i.x = VU->VF[_Fs_].i.y; + if (_Y) VU->VF[_Ft_].i.y = VU->VF[_Fs_].i.z; + if (_Z) VU->VF[_Ft_].i.z = VU->VF[_Fs_].i.w; + if (_W) VU->VF[_Ft_].i.w = tx; +}//last updated 23/10/03 linuzappz + +void _vuLQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQD( VURegs * VU ) { + u32 addr; + u32 *ptr; + + if (_Fs_ != 0) VU->VI[_Fs_].US[0]--; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQI(VURegs * VU) { + if (_Ft_) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; + } + if (_Fs_ != 0) VU->VI[_Fs_].US[0]++; +} + +/* addr is now signed. Asadr */ +void _vuSQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Ft_].SS[0]) * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQD(VURegs * VU) { + u32 addr; + u32 *ptr; + + if(_Ft_ != 0) VU->VI[_Ft_].US[0]--; + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQI(VURegs * VU) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; + if(_Ft_ != 0) VU->VI[_Ft_].US[0]++; +} + +/* addr now signed. asadr */ +void _vuILW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +void _vuILWR(VURegs * VU) { + u32 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISWR(VURegs * VU) { + u32 addr; + u16 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +/* code contributed by _Riff_ + +The following code implements a Galois form M-series LFSR that can be configured to have a width from 0 to 32. +A Galois field can be represented as G(X) = g_m * X^m + g_(m-1) * X^(m-1) + ... + g_1 * X^1 + g0. +A Galois form M-Series LFSR represents a Galois field where g0 = g_m = 1 and the generated set contains 2^M - 1 values. +In modulo-2 arithmetic, addition is replaced by XOR and multiplication is replaced by AND. +The code is written in such a way that the polynomial lsb (g0) should be set to 0 and g_m is not represented. +As an example for setting the polynomial variable correctly, the 23-bit M-series generating polynomial X^23+X^14 + would be specified as (1 << 14). +*/ + + +//The two-tap 23 stage M-series polynomials are x23+x18 and x23+x14 ((1 << 18) and (1 << 14), respectively). +//The reverse sequences can be generated by x23+x(23-18) and x23+x(23-14) ((1 << 9) and (1 << 5), respectively) +u32 poly = 1 << 5; + +void SetPoly(u32 newPoly) { + poly = poly & ~1; +} + +void AdvanceLFSR(VURegs * VU) { + // code from www.project-fao.org + int x = (VU->VI[REG_R].UL >> 4) & 1; + int y = (VU->VI[REG_R].UL >> 22) & 1; + VU->VI[REG_R].UL <<= 1; + VU->VI[REG_R].UL ^= x ^ y; + VU->VI[REG_R].UL = (VU->VI[REG_R].UL&0x7fffff)|0x3f800000; +} +// old +// u32 lfsr = VU->VI[REG_R].UL & 0x007FFFFF; +// u32 oldlfsr = lfsr; +// lfsr <<= 1; +// if (oldlfsr & 0x00400000) { +// lfsr ^= poly; +// lfsr |= 1; +// } +// +// VU->VI[REG_R].UL = 0x3F800000 | (lfsr & 0x007FFFFF); + +void _vuRINIT(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | (VU->VF[_Fs_].UL[_Fsf_] & 0x007FFFFF); +} + +void _vuRGET(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRNEXT(VURegs * VU) { + if (_Ft_ == 0) return; + AdvanceLFSR(VU); + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRXOR(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | ((VU->VI[REG_R].UL ^ VU->VF[_Fs_].UL[_Fsf_]) & 0x007FFFFF); +} + +void _vuWAITQ(VURegs * VU) { +} + +void _vuFSAND(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) & imm; +} + +void _vuFSEQ(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + if((VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) == imm) VU->VI[_Ft_].US[0] = 1; + else VU->VI[_Ft_].US[0] = 0; +} + +void _vuFSOR(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) | imm; +} + +void _vuFSSET(VURegs * VU) { + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + VU->statusflag = (imm & 0xFC0) | (VU->VI[REG_STATUS_FLAG].US[0] & 0x3F); +} + +void _vuFMAND(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[_Fs_].US[0] & (VU->VI[REG_MAC_FLAG].UL & 0xFFFF); +} + +void _vuFMEQ(VURegs * VU) { + if(_Ft_ == 0) return; + if((VU->VI[REG_MAC_FLAG].UL & 0xFFFF) == VU->VI[_Fs_].US[0]){ + VU->VI[_Ft_].US[0] =1;} else { VU->VI[_Ft_].US[0] =0; } +} + +void _vuFMOR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_MAC_FLAG].UL & 0xFFFF) | VU->VI[_Fs_].US[0]; +} + +void _vuFCAND(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) & (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCEQ(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) == (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCOR(VURegs * VU) { + u32 hold = (VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) | ( VU->code & 0xFFFFFF); + if(hold == 0xFFFFFF) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCSET(VURegs * VU) { + VU->clipflag = (u32) (VU->code & 0xFFFFFF); + VU->VI[REG_CLIP_FLAG].UL = (u32) (VU->code & 0xFFFFFF); +} + +void _vuFCGET(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[REG_CLIP_FLAG].UL & 0x0FFF; +} + +s32 _branchAddr(VURegs * VU) { + s32 bpc = VU->VI[REG_TPC].SL + _Imm11_ * 8; + if (bpc < 0) { + bpc = VU->VI[REG_TPC].SL + _UImm11_ * 8; + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void _setBranch(VURegs * VU, u32 bpc) { + VU->branch = 2; + VU->branchpc = bpc; +// VU->vuExec(VU); +// VU->VI[REG_TPC].UL = bpc; +} + +void _vuIBEQ(VURegs * VU) { + if (VU->VI[_Ft_].US[0] == VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] >= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] > 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] <= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] < 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBNE(VURegs * VU) { + if (VU->VI[_Ft_].US[0] != VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuB(VURegs * VU) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); +} + +void _vuBAL(VURegs * VU) { + s32 bpc = _branchAddr(VU); + + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuJR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + _setBranch(VU, bpc); +} + +void _vuJALR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuMFP(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].i.x = VU->VI[REG_P].UL; + if (_Y) VU->VF[_Ft_].i.y = VU->VI[REG_P].UL; + if (_Z) VU->VF[_Ft_].i.z = VU->VI[REG_P].UL; + if (_W) VU->VF[_Ft_].i.w = VU->VI[REG_P].UL; +} + +void _vuWAITP(VURegs * VU) { +} + +void _vuESADD(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + VU->p.F = p; +} + +void _vuERSADD(VURegs * VU) { + float p = (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x)) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y)) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z)); + if (p != 0.0) + p = 1.0f / p; + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to value being -ve for sqrt *asadr */ +void _vuELENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if(p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERLENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if (p >= 0) { + p = fpusqrtf(p); + if (p != 0) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxy(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.y), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxz(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.z), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +void _vuESUM(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Fs_].i.w); + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERCPR(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p != 0){ + p = 1.0 / p; + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to Value being -ve for sqrt *asadr */ +void _vuESQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERSQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0) { + p = fpusqrtf(p); + if (p) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +void _vuESIN(VURegs * VU) { + float p = fpusinf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEATAN(VURegs * VU) { + float p = fpuatanf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEEXP(VURegs * VU) { + float p = fpuexpf(-(vuDouble(VU->VF[_Fs_].UL[_Fsf_]))); + VU->p.F = p; +} + +void _vuXITOP(VURegs * VU) { + if (_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->vifRegs->itop; +} + +void _vuXGKICK(VURegs * VU) +{ + // flush all pipelines first (in the right order) + _vuFlushAll(VU); + GSgifTransfer1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff); +} + +void _vuXTOP(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (u16)VU->vifRegs->top; +} + +#define GET_VF0_FLAG(reg) (((reg)==0)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_I)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_Q)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_I)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_Q)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Ft_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw = 0xff; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (_Ft_ ? GET_VF0_FLAG(_Fs_) : 0); \ +} + +#define VUREGS_IDISIT(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Fd_; \ + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); \ +} + +#define VUREGS_ITIS(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Ft_; \ + VUregsn->VIread = 1 << _Fs_; \ +} + +#define VUREGS_PFS(OP, _cycles) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_EFU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << REG_P; \ + VUregsn->VIread = GET_VF0_FLAG(_Fs_); \ + VUregsn->cycles = _cycles; \ +} + + + +VUREGS_FTFS(ABS); + +VUREGS_FDFSFT(ADD, 0); +VUREGS_FDFSI(ADDi, 0); +VUREGS_FDFSQ(ADDq, 0); +VUREGS_FDFSFTx(ADDx, 0); +VUREGS_FDFSFTy(ADDy, 0); +VUREGS_FDFSFTz(ADDz, 0); +VUREGS_FDFSFTw(ADDw, 0); + +VUREGS_ACCFSFT(ADDA, 0); +VUREGS_ACCFSI(ADDAi, 0); +VUREGS_ACCFSQ(ADDAq, 0); +VUREGS_ACCFSFTx(ADDAx, 0); +VUREGS_ACCFSFTy(ADDAy, 0); +VUREGS_ACCFSFTz(ADDAz, 0); +VUREGS_ACCFSFTw(ADDAw, 0); + +VUREGS_FDFSFT(SUB, 0); +VUREGS_FDFSI(SUBi, 0); +VUREGS_FDFSQ(SUBq, 0); +VUREGS_FDFSFTx(SUBx, 0); +VUREGS_FDFSFTy(SUBy, 0); +VUREGS_FDFSFTz(SUBz, 0); +VUREGS_FDFSFTw(SUBw, 0); + +VUREGS_ACCFSFT(SUBA, 0); +VUREGS_ACCFSI(SUBAi, 0); +VUREGS_ACCFSQ(SUBAq, 0); +VUREGS_ACCFSFTx(SUBAx, 0); +VUREGS_ACCFSFTy(SUBAy, 0); +VUREGS_ACCFSFTz(SUBAz, 0); +VUREGS_ACCFSFTw(SUBAw, 0); + +#define VUREGS_FDFSFTxyzw_MUL(OP, ACC, xyzw) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + if( _Ft_ == 0 && xyzw > 1 && _XYZW == 0xf ) { /* resetting to 0 */ \ + VUregsn->pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = (ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = GET_VF0_FLAG(_Fs_)|((ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 0; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_NONE; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_FTFS(FTOI0); +VUREGS_FTFS(FTOI4); +VUREGS_FTFS(FTOI12); +VUREGS_FTFS(FTOI15); +VUREGS_FTFS(ITOF0); +VUREGS_FTFS(ITOF4); +VUREGS_FTFS(ITOF12); +VUREGS_FTFS(ITOF15); + +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0x1; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1 << REG_CLIP_FLAG); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFr0xyzw = 0; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw = 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 12; +} + +VUREGS_ITIS(IADDI); +VUREGS_ITIS(IADDIU); +VUREGS_IDISIT(IADD); +VUREGS_IDISIT(IAND); +VUREGS_IDISIT(IOR); +VUREGS_IDISIT(ISUB); +VUREGS_ITIS(ISUBIU); + +VUREGS_FTFS(MOVE); + +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +VUREGS_FTFS(MR32); + +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = (1 << _Ft_); + VUregsn->VIread = (1 << _Fs_); +} + +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = (1 << REG_R)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_STATUS_FLAG; + VUregsn->VIread = 0;//1 << REG_STATUS_FLAG; this kills speed +} + +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = 0; +} + +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_P; +} + +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_EFU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_PFS(ESADD, 10); +VUREGS_PFS(ERSADD, 17); +VUREGS_PFS(ELENG, 17); +VUREGS_PFS(ERLENG, 23); +VUREGS_PFS(EATANxy, 53); +VUREGS_PFS(EATANxz, 53); +VUREGS_PFS(ESUM, 11); +VUREGS_PFS(ERCPR, 11); +VUREGS_PFS(ESQRT, 11); +VUREGS_PFS(ERSQRT, 17); +VUREGS_PFS(ESIN, 28); +VUREGS_PFS(EATAN, 53); +VUREGS_PFS(EEXP, 43); + +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_XGKICK; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} diff --git a/VUops.h b/VUops.h new file mode 100644 index 0000000000..0b4a0f9827 --- /dev/null +++ b/VUops.h @@ -0,0 +1,393 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU1OPS_H__ +#define __VU1OPS_H__ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include "VU.h" + +#define float_to_int4(x) (s32)((float)x * (1.0f / 0.0625f)) +#define float_to_int12(x) (s32)((float)x * (1.0f / 0.000244140625f)) +#define float_to_int15(x) (s32)((float)x * (1.0f / 0.000030517578125)) + +#define int4_to_float(x) (float)((float)x * 0.0625f) +#define int12_to_float(x) (float)((float)x * 0.000244140625f) +#define int15_to_float(x) (float)((float)x * 0.000030517578125) + +#define MAC_Reset( VU ) VU->VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF) + +void _vuSetCycleFlags(VURegs * VU); +void _vuFlushFDIV(VURegs * VU); +void _vuFlushEFU(VURegs * VU); +void _vuTestPipes(VURegs * VU); +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuABS(VURegs * VU); +void _vuADD(VURegs * VU); +void _vuADDi(VURegs * VU); +void _vuADDq(VURegs * VU); +void _vuADDx(VURegs * VU); +void _vuADDy(VURegs * VU); +void _vuADDz(VURegs * VU); +void _vuADDw(VURegs * VU); +void _vuADDA(VURegs * VU); +void _vuADDAi(VURegs * VU); +void _vuADDAq(VURegs * VU); +void _vuADDAx(VURegs * VU); +void _vuADDAy(VURegs * VU); +void _vuADDAz(VURegs * VU); +void _vuADDAw(VURegs * VU); +void _vuSUB(VURegs * VU); +void _vuSUBi(VURegs * VU); +void _vuSUBq(VURegs * VU); +void _vuSUBx(VURegs * VU); +void _vuSUBy(VURegs * VU); +void _vuSUBz(VURegs * VU); +void _vuSUBw(VURegs * VU); +void _vuSUBA(VURegs * VU); +void _vuSUBAi(VURegs * VU); +void _vuSUBAq(VURegs * VU); +void _vuSUBAx(VURegs * VU); +void _vuSUBAy(VURegs * VU); +void _vuSUBAz(VURegs * VU); +void _vuSUBAw(VURegs * VU); +void _vuMUL(VURegs * VU); +void _vuMULi(VURegs * VU); +void _vuMULq(VURegs * VU); +void _vuMULx(VURegs * VU); +void _vuMULy(VURegs * VU); +void _vuMULz(VURegs * VU); +void _vuMULw(VURegs * VU); +void _vuMULA(VURegs * VU); +void _vuMULAi(VURegs * VU); +void _vuMULAq(VURegs * VU); +void _vuMULAx(VURegs * VU); +void _vuMULAy(VURegs * VU); +void _vuMULAz(VURegs * VU); +void _vuMULAw(VURegs * VU); +void _vuMADD(VURegs * VU) ; +void _vuMADDi(VURegs * VU); +void _vuMADDq(VURegs * VU); +void _vuMADDx(VURegs * VU); +void _vuMADDy(VURegs * VU); +void _vuMADDz(VURegs * VU); +void _vuMADDw(VURegs * VU); +void _vuMADDA(VURegs * VU); +void _vuMADDAi(VURegs * VU); +void _vuMADDAq(VURegs * VU); +void _vuMADDAx(VURegs * VU); +void _vuMADDAy(VURegs * VU); +void _vuMADDAz(VURegs * VU); +void _vuMADDAw(VURegs * VU); +void _vuMSUB(VURegs * VU); +void _vuMSUBi(VURegs * VU); +void _vuMSUBq(VURegs * VU); +void _vuMSUBx(VURegs * VU); +void _vuMSUBy(VURegs * VU); +void _vuMSUBz(VURegs * VU) ; +void _vuMSUBw(VURegs * VU) ; +void _vuMSUBA(VURegs * VU); +void _vuMSUBAi(VURegs * VU); +void _vuMSUBAq(VURegs * VU); +void _vuMSUBAx(VURegs * VU); +void _vuMSUBAy(VURegs * VU); +void _vuMSUBAz(VURegs * VU); +void _vuMSUBAw(VURegs * VU); +void _vuMAX(VURegs * VU); +void _vuMAXi(VURegs * VU); +void _vuMAXx(VURegs * VU); +void _vuMAXy(VURegs * VU); +void _vuMAXz(VURegs * VU); +void _vuMAXw(VURegs * VU); +void _vuMINI(VURegs * VU); +void _vuMINIi(VURegs * VU); +void _vuMINIx(VURegs * VU); +void _vuMINIy(VURegs * VU); +void _vuMINIz(VURegs * VU); +void _vuMINIw(VURegs * VU); +void _vuOPMULA(VURegs * VU); +void _vuOPMSUB(VURegs * VU); +void _vuNOP(VURegs * VU); +void _vuFTOI0(VURegs * VU); +void _vuFTOI4(VURegs * VU); +void _vuFTOI12(VURegs * VU); +void _vuFTOI15(VURegs * VU); +void _vuITOF0(VURegs * VU) ; +void _vuITOF4(VURegs * VU) ; +void _vuITOF12(VURegs * VU); +void _vuITOF15(VURegs * VU); +void _vuCLIP(VURegs * VU); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuDIV(VURegs * VU); +void _vuSQRT(VURegs * VU); +void _vuRSQRT(VURegs * VU); +void _vuIADDI(VURegs * VU); +void _vuIADDIU(VURegs * VU); +void _vuIADD(VURegs * VU); +void _vuIAND(VURegs * VU); +void _vuIOR(VURegs * VU); +void _vuISUB(VURegs * VU); +void _vuISUBIU(VURegs * VU); +void _vuMOVE(VURegs * VU); +void _vuMFIR(VURegs * VU); +void _vuMTIR(VURegs * VU); +void _vuMR32(VURegs * VU); +void _vuLQ(VURegs * VU) ; +void _vuLQD(VURegs * VU); +void _vuLQI(VURegs * VU); +void _vuSQ(VURegs * VU); +void _vuSQD(VURegs * VU); +void _vuSQI(VURegs * VU); +void _vuILW(VURegs * VU); +void _vuISW(VURegs * VU); +void _vuILWR(VURegs * VU); +void _vuISWR(VURegs * VU); +void _vuLOI(VURegs * VU); +void _vuRINIT(VURegs * VU); +void _vuRGET(VURegs * VU); +void _vuRNEXT(VURegs * VU); +void _vuRXOR(VURegs * VU); +void _vuWAITQ(VURegs * VU); +void _vuFSAND(VURegs * VU); +void _vuFSEQ(VURegs * VU); +void _vuFSOR(VURegs * VU); +void _vuFSSET(VURegs * VU); +void _vuFMAND(VURegs * VU); +void _vuFMEQ(VURegs * VU); +void _vuFMOR(VURegs * VU); +void _vuFCAND(VURegs * VU); +void _vuFCEQ(VURegs * VU); +void _vuFCOR(VURegs * VU); +void _vuFCSET(VURegs * VU); +void _vuFCGET(VURegs * VU); +void _vuIBEQ(VURegs * VU); +void _vuIBGEZ(VURegs * VU); +void _vuIBGTZ(VURegs * VU); +void _vuIBLEZ(VURegs * VU); +void _vuIBLTZ(VURegs * VU); +void _vuIBNE(VURegs * VU); +void _vuB(VURegs * VU); +void _vuBAL(VURegs * VU); +void _vuJR(VURegs * VU); +void _vuJALR(VURegs * VU); +void _vuMFP(VURegs * VU); +void _vuWAITP(VURegs * VU); +void _vuESADD(VURegs * VU); +void _vuERSADD(VURegs * VU); +void _vuELENG(VURegs * VU); +void _vuERLENG(VURegs * VU); +void _vuEATANxy(VURegs * VU); +void _vuEATANxz(VURegs * VU); +void _vuESUM(VURegs * VU); +void _vuERCPR(VURegs * VU); +void _vuESQRT(VURegs * VU); +void _vuERSQRT(VURegs * VU); +void _vuESIN(VURegs * VU); +void _vuEATAN(VURegs * VU); +void _vuEEXP(VURegs * VU); +void _vuXITOP(VURegs * VU); +void _vuXGKICK(VURegs * VU); +void _vuXTOP(VURegs * VU); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuRegsABS(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMUL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAX(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsNOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUBIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMOVE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLOI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsELENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERLENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESUM(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERCPR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESIN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATAN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEEXP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn); + +#endif diff --git a/Vif.c b/Vif.c new file mode 100644 index 0000000000..385d145e0b --- /dev/null +++ b/Vif.c @@ -0,0 +1,2950 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "ix86/ix86.h" +#include "Vif.h" +#include "VUmicro.h" + +#include + +VIFregisters *_vifRegs; +u32* _vifMaskRegs = NULL; +__declspec(align(16)) u32 g_vifRow0[4], g_vifCol0[4], g_vifRow1[4], g_vifCol1[4]; +u32* _vifRow = NULL; + +vifStruct *_vif; + +static int n; +static int i; + +__inline static int _limit( int a, int max ) +{ + return ( a > max ? max : a ); +} + +#define _UNPACKpart( offnum, func ) \ + if ( ( size > 0 ) && ( _vifRegs->offset == offnum ) ) { \ + func; \ + size--; \ + _vifRegs->offset++; \ + } + +#define _UNPACKpart_nosize( offnum, func ) \ + if ( ( _vifRegs->offset == offnum ) ) { \ + func; \ + _vifRegs->offset++; \ + } + +static void _writeX( u32 *dest, u32 data ) +{ + //int n; + + switch ( _vif->cl ) { + case 0: n = 0; break; + case 1: n = 8; break; + case 2: n = 16; break; + default: n = 24; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeX %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r0; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +#ifdef VIF_LOG + VIF_LOG("_writeX-done : Data %x : Row %x\n", *dest, _vifRegs->r0); +#endif +} + +static void _writeY( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 2; break; + case 1: n = 10; break; + case 2: n = 18; break; + default: n = 26; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeY %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r1; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +#ifdef VIF_LOG + VIF_LOG("_writeY-done : Data %x : Row %x\n", *dest, _vifRegs->r1); +#endif +} + +static void _writeZ( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 4; break; + case 1: n = 12; break; + case 2: n = 20; break; + default: n = 28; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeZ %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r2; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void _writeW( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 6; break; + case 1: n = 14; break; + case 2: n = 22; break; + default: n = 30; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeW %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r3; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void writeX( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeX(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeX %8.8x : Mode %d, r0 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r0,data + _vifRegs->r0); +#endif +} + +static void writeY( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeY(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeY %8.8x : Mode %d, r1 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r1,data + _vifRegs->r1); +#endif +} + +static void writeZ( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeZ(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeZ %8.8x : Mode %d, r2 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r2,data + _vifRegs->r2); +#endif +} + +static void writeW( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeW(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeW %8.8x : Mode %d, r3 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r3,data + _vifRegs->r3); +#endif +} + +void UNPACK_S_32(u32 *dest, u32 *data) { + writeX(dest++, *data); + writeY(dest++, *data); + writeZ(dest++, *data); + writeW(dest++, *data++); +} + +int UNPACK_S_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data) ); + _UNPACKpart(1, writeY(dest++, *data) ); + _UNPACKpart(2, writeZ(dest++, *data) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (u32)data - (u32)_data; +} + +#define _UNPACK_S_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata); \ + writeY(dest++, *sdata); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); + +void UNPACK_S_16s( u32 *dest, u32 *data ) { + _UNPACK_S_16( s16 ); +} + +void UNPACK_S_16u( u32 *dest, u32 *data ) { + _UNPACK_S_16( u16 ); +} + +#define _UNPACK_S_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata) ); \ + _UNPACKpart(1, writeY(dest++, *sdata) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_S_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(s16); +} + +int UNPACK_S_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(u16); +} + +#define _UNPACK_S_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata); \ + writeY(dest++, *cdata); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_S_8s(u32 *dest, u32 *data) { + _UNPACK_S_8(s8); +} + +void UNPACK_S_8u(u32 *dest, u32 *data) { + _UNPACK_S_8(u8); +} + +#define _UNPACK_S_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata) ); \ + _UNPACKpart(1, writeY(dest++, *cdata) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_S_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(s8); +} + +int UNPACK_S_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(u8); +} + +void UNPACK_V2_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, 0); + writeW(dest++, 0); + +} + +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++)); + _UNPACKpart(1, writeY(dest++, *data++)); + _UNPACKpart_nosize(2, writeZ(dest++, 0)); + _UNPACKpart_nosize(3, writeW(dest++, 0)); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V2_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, 0); \ + writeW(dest++, 0); \ + + +void UNPACK_V2_16s(u32 *dest, u32 *data) { + _UNPACK_V2_16(s16); +} + +void UNPACK_V2_16u(u32 *dest, u32 *data) { + _UNPACK_V2_16(u16); +} + +#define _UNPACK_V2_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V2_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(s16); +} + +int UNPACK_V2_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(u16); +} + +#define _UNPACK_V2_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, 0); \ + writeW(dest++, 0); + +void UNPACK_V2_8s(u32 *dest, u32 *data) { + _UNPACK_V2_8(s8); +} + +void UNPACK_V2_8u(u32 *dest, u32 *data) { + _UNPACK_V2_8(u8); +} + +#define _UNPACK_V2_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V2_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(s8); +} + +int UNPACK_V2_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(u8); +} + +void UNPACK_V3_32(u32 *dest, u32 *data) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data++); + writeW(dest++, 0); +} + +int UNPACK_V3_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++); ); + _UNPACKpart(1, writeY(dest++, *data++); ); + _UNPACKpart(2, writeZ(dest++, *data++); ); + _UNPACKpart_nosize(3, writeW(dest++, 0); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V3_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata++); \ + writeW(dest++, 0); + +void UNPACK_V3_16s(u32 *dest, u32 *data) { + _UNPACK_V3_16(s16); +} + +void UNPACK_V3_16u(u32 *dest, u32 *data) { + _UNPACK_V3_16(u16); +} + +#define _UNPACK_V3_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart(2, writeZ(dest++, *sdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V3_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(s16); +} + +int UNPACK_V3_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(u16); +} + +#define _UNPACK_V3_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata++); \ + writeW(dest++, 0); + +void UNPACK_V3_8s(u32 *dest, u32 *data) { + _UNPACK_V3_8(s8); +} + +void UNPACK_V3_8u(u32 *dest, u32 *data) { + _UNPACK_V3_8(u8); +} + +#define _UNPACK_V3_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart(2, writeZ(dest++, *cdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V3_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(s8); +} + +int UNPACK_V3_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(u8); +} + +void UNPACK_V4_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data++); + writeW(dest++, *data++); +} + +int UNPACK_V4_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++) ); + _UNPACKpart(1, writeY(dest++, *data++) ); + _UNPACKpart(2, writeZ(dest++, *data++) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V4_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata++); \ + writeW(dest++, *sdata++); + +void UNPACK_V4_16s(u32 *dest, u32 *data) { + _UNPACK_V4_16(s16); +} + +void UNPACK_V4_16u(u32 *dest, u32 *data) { + _UNPACK_V4_16(u16); +} + +#define _UNPACK_V4_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++) ); \ + _UNPACKpart(1, writeY(dest++, *sdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata++) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V4_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(s16); +} + +int UNPACK_V4_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(u16); +} + +#define _UNPACK_V4_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata++); \ + writeW(dest++, *cdata++); + +void UNPACK_V4_8s(u32 *dest, u32 *data) { + _UNPACK_V4_8(s8); +} + +void UNPACK_V4_8u(u32 *dest, u32 *data) { + _UNPACK_V4_8(u8); +} + +#define _UNPACK_V4_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++) ); \ + _UNPACKpart(1, writeY(dest++, *cdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata++) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V4_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(s8); +} + +int UNPACK_V4_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(u8); +} + +void UNPACK_V4_5(u32 *dest, u32 *data) { + u16 *sdata = (u16*)data; + u32 rgba; + + rgba = *sdata++; + writeX(dest++, (rgba & 0x001f) << 3); + writeY(dest++, (rgba & 0x03e0) >> 2); + writeZ(dest++, (rgba & 0x7c00) >> 7); + writeW(dest++, (rgba & 0x8000) >> 8); +} + +int UNPACK_V4_5part(u32 *dest, u32 *data, int size) { + u16 *sdata = (u16*)data; + u32 rgba; + + while (size > 0) { + rgba = *sdata++; + _UNPACKpart(0, writeX(dest++, (rgba & 0x001f) << 3); ); + _UNPACKpart(1, writeY(dest++, (rgba & 0x03e0) >> 2); ); + _UNPACKpart(2, writeZ(dest++, (rgba & 0x7c00) >> 7); ); + _UNPACKpart(3, writeW(dest++, (rgba & 0x8000) >> 8); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (u32)sdata - (u32)data; +} + +#if (defined(__i386__) || defined(__x86_64__)) + +// sse2 highly optimized vif (~200 separate functions are built) zerofrog(@gmail.com) +#include +#include + +__declspec(align(16)) u32 g_vif1Masks[64], g_vif0Masks[64]; +u32 g_vif1HasMask3[4] = {0}, g_vif0HasMask3[4] = {0}; + +//static const u32 writearr[4] = { 0xffffffff, 0, 0, 0 }; +//static const u32 rowarr[4] = { 0, 0xffffffff, 0, 0 }; +//static const u32 colarr[4] = { 0, 0, 0xffffffff, 0 }; +//static const u32 updatearr[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0 }; + +// arranged in writearr, rowarr, colarr, updatearr +static __declspec(align(16)) s_maskarr[16][4] = { + 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, + 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff, + 0xffff0000, 0x00000000, 0x0000ffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, + 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff, + 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff, + 0x00000000, 0xffff0000, 0x00000000, 0xffff0000, + 0x0000ffff, 0x00000000, 0xffff0000, 0xffffffff, + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x00000000, 0x00000000, 0x0000ffff, + 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, + 0x00000000, 0x00000000, 0x0000ffff, 0x0000ffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +u8 s_maskwrite[256]; +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask) +{ + u32 prev = 0; + FreezeXMMRegs(1); + + for(i = 0; i < 4; ++i, mask >>= 8, oldmask >>= 8, vif1masks += 16) { + + prev |= s_maskwrite[mask&0xff];//((mask&3)==3)||((mask&0xc)==0xc)||((mask&0x30)==0x30)||((mask&0xc0)==0xc0); + hasmask[i] = prev; + + if( (mask&0xff) != (oldmask&0xff) ) { + __m128i r0, r1, r2, r3; + r0 = _mm_load_si128((__m128i*)&s_maskarr[mask&15][0]); + r2 = _mm_unpackhi_epi16(r0, r0); + r0 = _mm_unpacklo_epi16(r0, r0); + + r1 = _mm_load_si128((__m128i*)&s_maskarr[(mask>>4)&15][0]); + r3 = _mm_unpackhi_epi16(r1, r1); + r1 = _mm_unpacklo_epi16(r1, r1); + + _mm_storel_pi((__m64*)&vif1masks[0], *(__m128*)&r0); + _mm_storel_pi((__m64*)&vif1masks[2], *(__m128*)&r1); + _mm_storeh_pi((__m64*)&vif1masks[4], *(__m128*)&r0); + _mm_storeh_pi((__m64*)&vif1masks[6], *(__m128*)&r1); + + _mm_storel_pi((__m64*)&vif1masks[8], *(__m128*)&r2); + _mm_storel_pi((__m64*)&vif1masks[10], *(__m128*)&r3); + _mm_storeh_pi((__m64*)&vif1masks[12], *(__m128*)&r2); + _mm_storeh_pi((__m64*)&vif1masks[14], *(__m128*)&r3); + } + } +} + +// msvc++ +#define VIF_SRC ecx +#define VIF_INC edx +#define VIF_DST edi + +// writing masks +#define UNPACK_Write0_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm MOVDQA qword ptr [VIF_DST+(DEST_OFFSET)], r0 \ +} \ + +#define UNPACK_Write1_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, VIF_INC \ +} \ + +#define UNPACK_Write0_Mask UNPACK_Write0_Regular +#define UNPACK_Write1_Mask UNPACK_Write1_Regular + +#define UNPACK_Write0_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + /* masked write (dest needs to be in edi) */ \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(CL) + 48] \ + /*__asm maskmovdqu r0, XMM_WRITEMASK*/ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pandn XMM_WRITEMASK, qword ptr [VIF_DST] \ + __asm por r0, XMM_WRITEMASK \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, 16 \ +} \ + +#define UNPACK_Write1_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0) + 48] \ + /* masked write (dest needs to be in edi) */ \ + /*__asm maskmovdqu r0, XMM_WRITEMASK*/ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pandn XMM_WRITEMASK, qword ptr [VIF_DST] \ + __asm por r0, XMM_WRITEMASK \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, VIF_INC \ +} \ + +#define UNPACK_Mask_SSE_0(r0) \ +{ \ + __asm pand r0, XMM_WRITEMASK \ + __asm por r0, XMM_ROWCOLMASK \ +} \ + +// once a qword is uncomprssed, applies masks and saves +// note: modifying XMM_WRITEMASK +#define UNPACK_Mask_SSE_1(r0) \ +{ \ + /* dest = row + write (only when mask=0), otherwise write */ \ + __asm pand r0, XMM_WRITEMASK \ + __asm por r0, XMM_ROWCOLMASK \ + __asm pand XMM_WRITEMASK, XMM_ROW \ + __asm paddd r0, XMM_WRITEMASK \ +} \ + +#define UNPACK_Mask_SSE_2(r0) \ +{ \ + /* dest = row + write (only when mask=0), otherwise write \ + row = row + write (only when mask = 0), otherwise row */ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pand XMM_WRITEMASK, XMM_ROW \ + __asm paddd XMM_ROW, r0 \ + __asm por r0, XMM_ROWCOLMASK \ + __asm paddd r0, XMM_WRITEMASK \ +} \ + +#define UNPACK_WriteMask_SSE_0 UNPACK_Mask_SSE_0 +#define UNPACK_WriteMask_SSE_1 UNPACK_Mask_SSE_1 +#define UNPACK_WriteMask_SSE_2 UNPACK_Mask_SSE_2 + +#define UNPACK_Regular_SSE_0(r0) + +#define UNPACK_Regular_SSE_1(r0) \ +{ \ + __asm paddd r0, XMM_ROW \ +} \ + +#define UNPACK_Regular_SSE_2(r0) \ +{ \ + __asm paddd r0, XMM_ROW \ + __asm movdqa XMM_ROW, r0 \ +} \ + +// setting up masks +#define UNPACK_Setup_Mask_SSE(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(CL) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(CL) + 32] \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(CL)] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Start_Setup_Mask_SSE_0(CL) UNPACK_Setup_Mask_SSE(CL); +#define UNPACK_Start_Setup_Mask_SSE_1(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(CL) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(CL) + 32] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Setup_Mask_SSE_0_1(CL) +#define UNPACK_Setup_Mask_SSE_1_1(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0)] \ +} \ + +#define UNPACK_Setup_Mask_SSE_2_1(CL) { \ + /* ignore CL, since vif.cycle.wl == 1 */ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(0) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(0) + 32] \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0)] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Setup_Mask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) + +// write mask always destroys XMM_WRITEMASK, so 0_0 = 1_0 +#define UNPACK_Setup_WriteMask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_0_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_1_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_2_1(CL) UNPACK_Setup_Mask_SSE_2_1(CL) + +#define UNPACK_Start_Setup_WriteMask_SSE_0(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_1(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_2(CL) UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Start_Setup_Regular_SSE_0(CL) +#define UNPACK_Start_Setup_Regular_SSE_1(CL) +#define UNPACK_Start_Setup_Regular_SSE_2(CL) +#define UNPACK_Setup_Regular_SSE_0_0(CL) +#define UNPACK_Setup_Regular_SSE_1_0(CL) +#define UNPACK_Setup_Regular_SSE_2_0(CL) +#define UNPACK_Setup_Regular_SSE_0_1(CL) +#define UNPACK_Setup_Regular_SSE_1_1(CL) +#define UNPACK_Setup_Regular_SSE_2_1(CL) + +#define UNPACK_INC_DST_0_Regular(qw) __asm add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Regular(qw) +#define UNPACK_INC_DST_0_Mask(qw) __asm add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Mask(qw) +#define UNPACK_INC_DST_0_WriteMask(qw) +#define UNPACK_INC_DST_1_WriteMask(qw) + +// unpacks for 1,2,3,4 elements (V3 uses this directly) +#define UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) \ +} \ + +// V3 uses this directly +#define UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3) \ +} \ + +#define UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(2) \ +} \ + +#define UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(1) \ +} \ + +// S-32 +// only when cl==1 +#define UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R3, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_S_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_S_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R1, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_S_32SSE_2A UNPACK_S_32SSE_2 + +#define UNPACK_S_32SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_S_32SSE_1A UNPACK_S_32SSE_1 + +// S-16 +#define UNPACK_S_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R3, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R3, XMM_R3 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_S_16SSE_4A UNPACK_S_16SSE_4 + +#define UNPACK_S_16SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R2, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_S_16SSE_3A UNPACK_S_16SSE_3 + +#define UNPACK_S_16SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R1, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_S_16SSE_2A UNPACK_S_16SSE_2 + +#define UNPACK_S_16SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_S_16SSE_1A UNPACK_S_16SSE_1 + +// S-8 +#define UNPACK_S_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R3, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R3, XMM_R3 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} + +#define UNPACK_S_8SSE_4A UNPACK_S_8SSE_4 + +#define UNPACK_S_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R2, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 3 \ + } \ +} \ + +#define UNPACK_S_8SSE_3A UNPACK_S_8SSE_3 + +#define UNPACK_S_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R1, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_S_8SSE_2A UNPACK_S_8SSE_2 + +#define UNPACK_S_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm inc VIF_SRC \ + } \ +} \ + +#define UNPACK_S_8SSE_1A UNPACK_S_8SSE_1 + +// V2-32 +#define UNPACK_V2_32SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm MOVDQA XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V2_32SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + __asm movq XMM_R3, qword ptr [VIF_SRC+24] \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V2_32SSE_3A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V2_32SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V2_32SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V2_32SSE_2A UNPACK_V2_32SSE_2 + +#define UNPACK_V2_32SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_32SSE_1A UNPACK_V2_32SSE_1 + +// V2-16 +#define UNPACK_V2_16SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V2_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V2_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V2_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V2_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, dword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V2_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +// V2-8 +#define UNPACK_V2_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_V2_8SSE_4A UNPACK_V2_8SSE_4 + +#define UNPACK_V2_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V2_8SSE_3A UNPACK_V2_8SSE_3 + +#define UNPACK_V2_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V2_8SSE_2A UNPACK_V2_8SSE_2 + +#define UNPACK_V2_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_V2_8SSE_1A UNPACK_V2_8SSE_1 + +// V3-32 +#define UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + } \ + { \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+24] \ + __asm movdqu XMM_R3, qword ptr [VIF_SRC+36] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) \ + } \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V3_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + } \ + { \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+24] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3) \ + } \ + { \ + __asm add VIF_SRC, 36 \ + } \ +} \ + +#define UNPACK_V3_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V3_32SSE_2A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_2(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V3_32SSE_1A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_1(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqu) + +// V3-16 +#define UNPACK_V3_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm movq XMM_R2, qword ptr [VIF_SRC+12] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm movq XMM_R3, qword ptr [VIF_SRC+18] \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} + +#define UNPACK_V3_16SSE_4A UNPACK_V3_16SSE_4 + +#define UNPACK_V3_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm movq XMM_R2, qword ptr [VIF_SRC+12] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 18 \ + } \ +} \ + +#define UNPACK_V3_16SSE_3A UNPACK_V3_16SSE_3 + +#define UNPACK_V3_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V3_16SSE_2A UNPACK_V3_16SSE_2 + +#define UNPACK_V3_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V3_16SSE_1A UNPACK_V3_16SSE_1 + +// V3-8 +#define UNPACK_V3_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R1, qword ptr [VIF_SRC] \ + __asm movq XMM_R3, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklbw XMM_R3, XMM_R3 \ + __asm punpcklwd XMM_R0, XMM_R1 \ + __asm psrldq XMM_R1, 6 \ + __asm punpcklwd XMM_R2, XMM_R3 \ + __asm psrldq XMM_R3, 6 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} + +#define UNPACK_V3_8SSE_4A UNPACK_V3_8SSE_4 + +#define UNPACK_V3_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, word ptr [VIF_SRC] \ + __asm movd XMM_R1, dword ptr [VIF_SRC+3] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm movd XMM_R2, dword ptr [VIF_SRC+6] \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R2, XMM_R2 \ + \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 9 \ + } \ +} \ + +#define UNPACK_V3_8SSE_3A UNPACK_V3_8SSE_3 + +#define UNPACK_V3_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm movd XMM_R1, dword ptr [VIF_SRC+3] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R1, XMM_R1 \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V3_8SSE_2A UNPACK_V3_8SSE_2 + +#define UNPACK_V3_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 3 \ + } \ +} \ + +#define UNPACK_V3_8SSE_1A UNPACK_V3_8SSE_1 + +// V4-32 +#define UNPACK_V4_32SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqa XMM_R2, qword ptr [VIF_SRC+32] \ + __asm movdqa XMM_R3, qword ptr [VIF_SRC+48] \ + } \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 64 \ + } \ +} + +#define UNPACK_V4_32SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+32] \ + __asm movdqu XMM_R3, qword ptr [VIF_SRC+48] \ + } \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 64 \ + } \ +} + +#define UNPACK_V4_32SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqa XMM_R2, qword ptr [VIF_SRC+32] \ + } \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V4_32SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+32] \ + } \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V4_32SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_32SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_32SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_32SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +// V4-16 +#define UNPACK_V4_16SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, qword ptr [VIF_SRC+16] \ + __asm punpckhwd XMM_R3, qword ptr [VIF_SRC+16] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V4_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V4_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V4_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V4_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +// V4-8 +#define UNPACK_V4_8SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhbw XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_8SSE_3A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhbw XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V4_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movd XMM_R2, dword ptr [VIF_SRC+8] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R2, XMM_R2 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V4_8SSE_2A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_8SSE_1A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V4_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +// V4-5 +__declspec(align(16)) static u32 s_TempDecompress[4] = {0}; + +#define DECOMPRESS_RGBA(OFFSET) { \ + /* R */ \ + __asm mov bl, al \ + __asm shl bl, 3 \ + __asm mov byte ptr [s_TempDecompress+OFFSET], bl \ + /* G */ \ + __asm mov bx, ax \ + __asm shr bx, 2 \ + __asm and bx, 0xf8 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+1], bl \ + /* B */ \ + __asm mov bx, ax \ + __asm shr bx, 7 \ + __asm and bx, 0xf8 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+2], bl \ + __asm mov bx, ax \ + __asm shr bx, 8 \ + __asm and bx, 0x80 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+3], bl \ +} \ + +#define UNPACK_V4_5SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm mov ax, word ptr [VIF_SRC+4] \ + } \ + DECOMPRESS_RGBA(8); \ + { \ + __asm mov ax, word ptr [VIF_SRC+6] \ + } \ + DECOMPRESS_RGBA(12); \ + { \ + __asm movdqa XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + __asm psrld XMM_R2, 24 \ + __asm psrld XMM_R3, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_V4_5SSE_4A UNPACK_V4_5SSE_4 + +#define UNPACK_V4_5SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm mov ax, word ptr [VIF_SRC+4] \ + } \ + DECOMPRESS_RGBA(8); \ + { \ + __asm movdqa XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + __asm psrld XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V4_5SSE_3A UNPACK_V4_5SSE_3 + +#define UNPACK_V4_5SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm movq XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V4_5SSE_2A UNPACK_V4_5SSE_2 + +#define UNPACK_V4_5SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov ax, word ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm movd XMM_R0, dword ptr [s_TempDecompress] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm psrld XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_V4_5SSE_1A UNPACK_V4_5SSE_1 + +#pragma warning(disable:4731) + +#ifdef _DEBUG +#define PUSHESI __asm mov s_saveesi, esi +#define POPESI __asm mov esi, s_saveesi +#else +#define PUSHESI +#define POPESI +#endif + +#define PUSHEDI +#define POPEDI +#define PUSHEBP //__asm mov dword ptr [esp-4], ebp +#define POPEBP //__asm mov ebp, dword ptr [esp-4] + +//__asm mov eax, pr0 \ +///* load row */ \ +//__asm movss XMM_ROW, dword ptr [eax] \ +//__asm movss XMM_R1, dword ptr [eax+4] \ +//__asm punpckldq XMM_ROW, XMM_R1 \ +//__asm movss XMM_R0, dword ptr [eax+8] \ +//__asm movss XMM_R1, dword ptr [eax+12] \ +//__asm punpckldq XMM_R0, XMM_R1 \ +//__asm punpcklqdq XMM_ROW, XMM_R0 \ +//\ +//__asm mov eax, pc0 \ +//__asm movss XMM_R3, dword ptr [eax] \ +//__asm movss XMM_R1, dword ptr [eax+4] \ +//__asm punpckldq XMM_R3, XMM_R1 \ +//__asm movss XMM_R0, dword ptr [eax+8] \ +//__asm movss XMM_R1, dword ptr [eax+12] \ +//__asm punpckldq XMM_R0, XMM_R1 \ +//__asm punpcklqdq XMM_R3, XMM_R0 \ + +#define SAVE_ROW_REG_BASE { \ + { \ + /* save the row reg */ \ + __asm mov eax, _vifRow \ + __asm movdqa qword ptr [eax], XMM_ROW \ + __asm mov eax, _vifRegs \ + __asm movss dword ptr [eax+0x100], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x110], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x120], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x130], XMM_ROW \ + } \ +} \ + +#define SAVE_NO_REG + +extern int g_nCounters[4]; + +static int tempcl = 0, incdest; +static int s_saveesi, s_saveinc; + +// qsize - bytes of compressed size of 1 decompressed qword +#define defUNPACK_SkippingWrite(name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG) \ +int UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType##(u32* dest, u32* data, int dmasize) \ +{ \ + incdest = ((_vifRegs->cycle.cl - _vifRegs->cycle.wl)<<4); \ + \ + switch( _vifRegs->cycle.wl ) { \ + case 1: \ + { \ + /*__asm inc dword ptr [g_nCounters] \ + __asm mov eax, dmasize \ + __asm add dword ptr [g_nCounters+4], eax*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov esi, dmasize \ + } \ + UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ + { \ + __asm cmp esi, qsize \ + __asm jl C1_Done3 \ + \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm mov VIF_INC, incdest \ + __asm add VIF_INC, 16 \ + } \ + \ + /* first align VIF_SRC to 16 bytes */ \ +C1_Align16: \ + { \ + __asm test VIF_SRC, 15 \ + __asm jz C1_UnpackAligned \ + } \ + UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ + { \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_DoneWithDec \ + __asm sub esi, qsize \ + __asm jmp C1_Align16 \ + } \ +C1_UnpackAligned: \ + { \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_Unpack1 \ + __asm cmp esi, (3*qsize) \ + __asm jl C1_Unpack2 \ + __asm cmp esi, (4*qsize) \ + __asm jl C1_Unpack3 \ + __asm prefetchnta [eax + 192] \ + } \ +C1_Unpack4: \ + UNPACK_##name##SSE_4A(0, 1, MaskType, ModeType); \ + { \ + __asm cmp esi, (8*qsize) \ + __asm jl C1_DoneUnpack4 \ + __asm sub esi, (4*qsize) \ + __asm jmp C1_Unpack4 \ + } \ +C1_DoneUnpack4: \ + { \ + __asm sub esi, (4*qsize) \ + __asm cmp esi, qsize \ + __asm jl C1_Done3 \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_Unpack1 \ + __asm cmp esi, (3*qsize) \ + __asm jl C1_Unpack2 \ + /* fall through */ \ + } \ +C1_Unpack3: \ + UNPACK_##name##SSE_3A(0, 1, MaskType, ModeType); \ + { \ + __asm sub esi, (3*qsize) \ + __asm jmp C1_Done3 \ + } \ +C1_Unpack2: \ + UNPACK_##name##SSE_2A(0, 1, MaskType, ModeType); \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C1_Done3 \ + } \ +C1_Unpack1: \ + UNPACK_##name##SSE_1A(0, 1, MaskType, ModeType); \ +C1_DoneWithDec: \ + { \ + __asm sub esi, qsize \ + } \ +C1_Done3: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + case 2: \ + { \ + /*__asm inc dword ptr [g_nCounters+4]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, incdest \ + __asm mov esi, dmasize \ + __asm cmp esi, (2*qsize) \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm jl C2_Done3 \ + } \ +C2_Unpack: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + \ + { \ + __asm add VIF_DST, VIF_INC /* take into account wl */ \ + __asm cmp esi, (4*qsize) \ + __asm jl C2_Done2 \ + __asm sub esi, (2*qsize) \ + __asm jmp C2_Unpack /* unpack next */ \ + } \ +C2_Done2: \ + { \ + __asm sub esi, (2*qsize) \ + } \ +C2_Done3: \ + { \ + __asm cmp esi, qsize \ + __asm jl C2_Done4 \ + } \ + /* execute left over qw */ \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, qsize \ + } \ +C2_Done4: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + \ + case 3: \ + { \ + /*__asm inc dword ptr [g_nCounters+8]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, incdest \ + __asm mov esi, dmasize \ + __asm cmp esi, (3*qsize) \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm jl C3_Done5 \ + } \ +C3_Unpack: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + \ + { \ + __asm add VIF_DST, VIF_INC /* take into account wl */ \ + __asm cmp esi, (6*qsize) \ + __asm jl C3_Done2 \ + __asm sub esi, (3*qsize) \ + __asm jmp C3_Unpack /* unpack next */ \ + } \ +C3_Done2: \ + { \ + __asm sub esi, (3*qsize) \ + } \ +C3_Done5: \ + { \ + __asm cmp esi, qsize \ + __asm jl C3_Done4 \ + /* execute left over qw */ \ + __asm cmp esi, (2*qsize) \ + __asm jl C3_Done3 \ + } \ + \ + /* process 2 qws */ \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C3_Done4 \ + } \ + \ +C3_Done3: \ + /* process 1 qw */ \ + { \ + __asm sub esi, qsize \ + } \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ +C3_Done4: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + \ + default: /* >= 4 */ \ + tempcl = _vifRegs->cycle.wl-3; \ + { \ + /*__asm inc dword ptr [g_nCounters+12]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, tempcl \ + __asm mov s_saveinc, VIF_INC \ + __asm mov esi, dmasize \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + } \ +C4_Unpack: \ + { \ + __asm cmp esi, (3*qsize) \ + __asm jge C4_Unpack3 \ + __asm cmp esi, (2*qsize) \ + __asm jge C4_Unpack2 \ + } \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + /* not enough data left */ \ + { \ + __asm sub esi, qsize \ + __asm jmp C4_Done \ + } \ +C4_Unpack2: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + /* not enough data left */ \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C4_Done \ + } \ +C4_Unpack3: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, (3*qsize) \ + /* more data left, process 1qw at a time */ \ + __asm mov VIF_INC, s_saveinc \ + } \ +C4_UnpackX: \ + { \ + /* check if any data left */ \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + \ + } \ + UNPACK_##name##SSE_1(3, 0, MaskType, ModeType); \ + { \ + __asm sub esi, qsize \ + __asm cmp VIF_INC, 1 \ + __asm je C4_DoneLoop \ + __asm sub VIF_INC, 1 \ + __asm jmp C4_UnpackX \ + } \ +C4_DoneLoop: \ + { \ + __asm add VIF_DST, incdest /* take into account wl */ \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + __asm jmp C4_Unpack /* unpack next */ \ + } \ +C4_Done: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + } \ + \ + return dmasize; \ +} \ + +//{ \ +// /*__asm inc dword ptr [g_nCounters] \ +// __asm mov eax, dmasize \ +// __asm add dword ptr [g_nCounters+4], eax*/ \ +// PUSHESI \ +// PUSHEDI \ +// __asm mov esi, dmasize \ +// } \ +// UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ +// { \ +// __asm cmp esi, qsize \ +// __asm jl C1_Done3 \ +// \ +// /* move source and dest */ \ +// __asm mov VIF_DST, dest \ +// __asm mov VIF_SRC, data \ +// __asm mov VIF_INC, incdest \ +// __asm cmp esi, (2*qsize) \ +// __asm jl C1_Unpack1 \ +// __asm cmp esi, (3*qsize) \ +// __asm jl C1_Unpack2 \ +// __asm imul VIF_INC, 3 \ +// __asm prefetchnta [eax + 192] \ +// } \ +//C1_Unpack3: \ +// UNPACK_##name##SSE_3(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC /* take into account wl */ \ +// __asm cmp esi, (6*qsize) \ +// __asm jl C1_DoneUnpack3 \ +// __asm sub esi, (3*qsize) \ +// __asm jmp C1_Unpack3 \ +// } \ +//C1_DoneUnpack3: \ +// { \ +// __asm sub esi, (3*qsize) \ +// __asm mov VIF_INC, dword ptr [esp] /* restore old ptr */ \ +// __asm cmp esi, (2*qsize) \ +// __asm jl C1_Unpack1 \ +// /* fall through */ \ +// } \ +//C1_Unpack2: \ +// UNPACK_##name##SSE_2(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC \ +// __asm add VIF_DST, VIF_INC \ +// __asm sub esi, (2*qsize) \ +// __asm jmp C1_Done3 \ +// } \ +//C1_Unpack1: \ +// UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC /* take into account wl */ \ +// __asm sub esi, qsize \ +// } \ +//C1_Done3: \ +// { \ +// POPEDI \ +// __asm mov dmasize, esi \ +// POPESI \ +// } \ +// SAVE_ROW_REG; \ + +//while(size >= qsize) { +// funcP( dest, (u32*)cdata, chans); +// cdata += ft->qsize; +// size -= ft->qsize; +// +// if (vif->cl >= wl) { +// dest += incdest; +// vif->cl = 0; +// } +// else { +// dest += 4; +// vif->cl++; +// } +//} + +#define UNPACK_RIGHTSHIFT psrld +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE); \ + +defUNPACK_SkippingWrite2(S_32, 4); +defUNPACK_SkippingWrite2(S_16, 2); +defUNPACK_SkippingWrite2(S_8, 1); +defUNPACK_SkippingWrite2(V2_32, 8); +defUNPACK_SkippingWrite2(V2_16, 4); +defUNPACK_SkippingWrite2(V2_8, 2); +defUNPACK_SkippingWrite2(V3_32, 12); +defUNPACK_SkippingWrite2(V3_16, 6); +defUNPACK_SkippingWrite2(V3_8, 3); +defUNPACK_SkippingWrite2(V4_32, 16); +defUNPACK_SkippingWrite2(V4_16, 8); +defUNPACK_SkippingWrite2(V4_8, 4); +defUNPACK_SkippingWrite2(V4_5, 2); + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#define UNPACK_RIGHTSHIFT psrad +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE); \ + +defUNPACK_SkippingWrite2(S_16, 2); +defUNPACK_SkippingWrite2(S_8, 1); +defUNPACK_SkippingWrite2(V2_16, 4); +defUNPACK_SkippingWrite2(V2_8, 2); +defUNPACK_SkippingWrite2(V3_16, 6); +defUNPACK_SkippingWrite2(V3_8, 3); +defUNPACK_SkippingWrite2(V4_16, 8); +defUNPACK_SkippingWrite2(V4_8, 4); + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#endif + +static int cycles; + +int mfifoVIF1rbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((vif1ch->madr+(vif1ch->qwc << 4)) > (maddr+msize)) { + int s1 = (maddr+msize) - vif1ch->madr; + int s2 = (vif1ch->qwc << 4) - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + ret = VIF1transfer(src, s1/4, 0); + assert(ret == 0 ); // vif stall code not implemented + + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + ret = VIF1transfer(src, s2/4, 0); + assert(ret == 0 ); // vif stall code not implemented + } else { + /* it doesn't, so just transfer 'qwc*4' words + from 'vif1ch->madr' to VIF1 */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + ret = VIF1transfer(src, vif1ch->qwc << 2, 0); + assert(ret == 0 ); // vif stall code not implemented + } + + vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->madr = psHu32(DMAC_RBOR) + (vif1ch->madr & psHu32(DMAC_RBSR)); + + return 0; +} + +int mfifoVIF1chain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *pMem; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (vif1ch->qwc == 0) return 0; + + if (vif1ch->madr >= maddr && + vif1ch->madr < (maddr+msize)) { + if (mfifoVIF1rbTransfer() == -1) return -1; + } else { + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) return -1; + ret = VIF1transfer(pMem, vif1ch->qwc << 2, 0); + assert(ret == 0 ); // vif stall code not implemented + + vif1ch->madr+= (vif1ch->qwc << 4); + } + + cycles+= (vif1ch->qwc) * BIAS; /* guessing */ + vif1ch->qwc = 0; + + return 0; +} + +void mfifoVIF1transfer(int qwc) { + u32 *ptag; + int id; + int done = 0, ret; + cycles = 0; + +#ifdef VIF_LOG + VIF_LOG("mfifoVIF1transfer %x\n", vif1ch->chcr); +#endif + if((vif1ch->chcr & 0x100) == 0)SysPrintf("MFIFO VIF1 not ready!\n"); + while (qwc > 0 && done == 0) { + vif1ch->tadr = psHu32(DMAC_RBOR) + (vif1ch->tadr & psHu32(DMAC_RBSR)); + ptag = (u32*)dmaGetAddr(vif1ch->tadr); + + id = (ptag[0] >> 28) & 0x7; + vif1ch->qwc = (ptag[0] & 0xffff); + vif1ch->madr = ptag[1]; + cycles += 2; + if(vif1ch->chcr & 0x40) { + ret = VIF1transfer(ptag+2, 2, 1); + assert(ret == 0 ); // vif stall code not implemented + } + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr); +#endif + + switch (id) { + case 0: // refe + vif1ch->tadr += 16; + qwc = 0; + INT(10,cycles); + done = 1; + break; + + case 1: // cnt + vif1ch->madr = vif1ch->tadr + 16; + qwc-= vif1ch->qwc + 1; + // Set the taddr to the next tag + vif1ch->tadr += 16 + (vif1ch->qwc * 16); + break; + + case 3: // ref + case 4: // refs + vif1ch->tadr += 16; + qwc--; + break; + + case 7: // end + vif1ch->madr = vif1ch->tadr + 16; + vif1ch->tadr = vif1ch->madr + (vif1ch->qwc * 16); + qwc = 0; + INT(10,cycles); + done = 1; + break; + } + + if (mfifoVIF1chain() == -1) { + break; + } + + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef VIF_LOG + VIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("mfifoVIF1transfer: dmaIrq Set\n"); + qwc = 0; + done = 1; + INT(10,cycles); + } + } + if(done == 0 && qwc == 0)hwDmacIrq(14); + + vif1ch->tadr = psHu32(DMAC_RBOR) + (vif1ch->tadr & (psHu32(DMAC_RBSR))); + //hwDmacIrq(1); + + // restore + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vifMFIFOInterrupt() +{ + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); +// vif1ch->chcr &= ~0x100; +// vif1Regs->stat&= ~0x1F000000; // FQC=0 +// hwDmacIrq(DMAC_VIF1); +// +// if (vif1.irq > 0) { +// vif1.irq--; +// hwIntcIrq(5); // VIF1 Intc +// } + return 1; +} diff --git a/Vif.h b/Vif.h new file mode 100644 index 0000000000..749171d387 --- /dev/null +++ b/Vif.h @@ -0,0 +1,108 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VIF_H__ +#define __VIF_H__ + +typedef struct { + u8 cl, wl; + u8 pad[2]; +} vifCycle; + +typedef struct { + u32 stat; + u32 pad0[3]; + u32 fbrst; + u32 pad1[3]; + u32 err; + u32 pad2[3]; + u32 mark; + u32 pad3[3]; + vifCycle cycle; //data write cycle + u32 pad4[3]; + u32 mode; + u32 pad5[3]; + u32 num; + u32 pad6[3]; + u32 mask; + u32 pad7[3]; + u32 code; + u32 pad8[3]; + u32 itops; + u32 pad9[3]; + u32 base; // Not used in VIF0 + u32 pad10[3]; + u32 ofst; // Not used in VIF0 + u32 pad11[3]; + u32 tops; // Not used in VIF0 + u32 pad12[3]; + u32 itop; + u32 pad13[3]; + u32 top; // Not used in VIF0 + u32 pad14[3]; + u32 mskpath3; + u32 pad15[3]; + u32 r0; // row0 register + u32 pad16[3]; + u32 r1; // row1 register + u32 pad17[3]; + u32 r2; // row2 register + u32 pad18[3]; + u32 r3; // row3 register + u32 pad19[3]; + u32 c0; // col0 register + u32 pad20[3]; + u32 c1; // col1 register + u32 pad21[3]; + u32 c2; // col2 register + u32 pad22[3]; + u32 c3; // col3 register + u32 pad23[3]; + u32 offset; // internal UNPACK offset + u32 addr; +} VIFregisters; + +#define vif0Regs ((VIFregisters*)&PS2MEM_HW[0x3800]) +#define vif1Regs ((VIFregisters*)&PS2MEM_HW[0x3c00]) + +void dmaVIF0(); +void dmaVIF1(); +void mfifoVIF1transfer(int qwc); +int VIF0transfer(u32 *data, int size, int istag); +int VIF1transfer(u32 *data, int size, int istag); +int vifMFIFOInterrupt(); + +#if (defined(__i386__) || defined(__x86_64__)) +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask); +#else +#define SetNewMask 0&& +#endif + +#define XMM_R0 xmm0 +#define XMM_R1 xmm1 +#define XMM_R2 xmm2 +#define XMM_WRITEMASK xmm3 +#define XMM_ROWMASK xmm4 +#define XMM_ROWCOLMASK xmm5 +#define XMM_ROW xmm6 +#define XMM_COL xmm7 + +#define XMM_R3 XMM_COL + + +#endif /* __VIF_H__ */ diff --git a/VifDma.c b/VifDma.c new file mode 100644 index 0000000000..a6c75e4e48 --- /dev/null +++ b/VifDma.c @@ -0,0 +1,1872 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Vif.h" +#include "VUmicro.h" +#include "VifDma.h" + +#include + +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) + +// Extern variables +extern VIFregisters *_vifRegs; +extern vifStruct *_vif; +extern u32* _vifMaskRegs; +extern u32 g_vifRow0[4], g_vifCol0[4], g_vifRow1[4], g_vifCol1[4]; +extern u32* _vifRow; + +extern u32 g_vif1Masks[48], g_vif0Masks[48]; +extern u32 g_vif1HasMask3[4], g_vif0HasMask3[4]; + +#if (defined(__i386__) || defined(__x86_64__)) +#include +#include +#endif + +// Generic constants +static const unsigned int VIF0intc = 4; +static const unsigned int VIF1intc = 5; +static const unsigned int VIF0dmanum = 0; +static const unsigned int VIF1dmanum = 1; + +static int cycles; +extern HANDLE g_hGsEvent; +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +typedef void (*UNPACKFUNCTYPE)( u32 *dest, u32 *data ); +typedef int (*UNPACKPARTFUNCTYPE)( u32 *dest, u32 *data, int size ); + +typedef struct { + UNPACKFUNCTYPE funcU; + UNPACKFUNCTYPE funcS; + UNPACKPARTFUNCTYPE funcUpart; + UNPACKPARTFUNCTYPE funcSpart; + + int bsize; // total byte size of compressed data + int dsize; // byte size of one channel + int gsize; // repeat count + int qsize; // bytes of compressed size of 1 decompressed qword +} VIFUnpackFuncTable; + +/* block size; data size; group size; qword size; */ +#define _UNPACK_TABLE32(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name, UNPACK_##name, \ + UNPACK_##name##part, UNPACK_##name##part, \ + bsize, dsize, gsize, qsize }, + +#define _UNPACK_TABLE(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name##u, UNPACK_##name##s, \ + UNPACK_##name##upart, UNPACK_##name##spart, \ + bsize, dsize, gsize, qsize }, + +// Main table for function unpacking +static const VIFUnpackFuncTable VIFfuncTable[16] = { + _UNPACK_TABLE32(S_32, 12, 4, 4, 4) // 0x0 - S-32 + _UNPACK_TABLE(S_16, 6, 2, 4, 2) // 0x1 - S-16 + _UNPACK_TABLE(S_8, 3, 1, 4, 1) // 0x2 - S-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x3 + + _UNPACK_TABLE32(V2_32, 24, 4, 1, 8) // 0x4 - V2-32 + _UNPACK_TABLE(V2_16, 12, 2, 1, 4) // 0x5 - V2-16 + _UNPACK_TABLE(V2_8, 6, 1, 1, 2) // 0x6 - V2-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x7 + + _UNPACK_TABLE32(V3_32, 36, 4, 1, 12) // 0x8 - V3-32 + _UNPACK_TABLE(V3_16, 18, 2, 1, 6) // 0x9 - V3-16 + _UNPACK_TABLE(V3_8, 9, 1, 1, 3) // 0xA - V3-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0xB + + _UNPACK_TABLE32(V4_32, 48, 4, 1, 16) // 0xC - V4-32 + _UNPACK_TABLE(V4_16, 24, 2, 1, 8) // 0xD - V4-16 + _UNPACK_TABLE(V4_8, 12, 1, 1, 4) // 0xE - V4-8 + _UNPACK_TABLE32(V4_5, 6, 2, 1, 8) // 0xF - V4-5 +}; + +#if (defined(__i386__) || defined(__x86_64__)) + +typedef struct { + // regular 0, 1, 2; mask 0, 1, 2 + UNPACKPARTFUNCTYPE funcU[9], funcS[9]; +} VIFSSEUnpackTable; + +#define DECL_UNPACK_TABLE_SSE(name, sign) \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2(u32* dest, u32* data, int dmasize); \ + +#define _UNPACK_TABLE_SSE(name, sign) \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_2, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_2, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2 \ + +#define _UNPACK_TABLE_SSE_NULL \ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + +// Main table for function unpacking +DECL_UNPACK_TABLE_SSE(S_32, u); +DECL_UNPACK_TABLE_SSE(S_16, u); +DECL_UNPACK_TABLE_SSE(S_8, u); +DECL_UNPACK_TABLE_SSE(S_16, s); +DECL_UNPACK_TABLE_SSE(S_8, s); + +DECL_UNPACK_TABLE_SSE(V2_32, u); +DECL_UNPACK_TABLE_SSE(V2_16, u); +DECL_UNPACK_TABLE_SSE(V2_8, u); +DECL_UNPACK_TABLE_SSE(V2_16, s); +DECL_UNPACK_TABLE_SSE(V2_8, s); + +DECL_UNPACK_TABLE_SSE(V3_32, u); +DECL_UNPACK_TABLE_SSE(V3_16, u); +DECL_UNPACK_TABLE_SSE(V3_8, u); +DECL_UNPACK_TABLE_SSE(V3_16, s); +DECL_UNPACK_TABLE_SSE(V3_8, s); + +DECL_UNPACK_TABLE_SSE(V4_32, u); +DECL_UNPACK_TABLE_SSE(V4_16, u); +DECL_UNPACK_TABLE_SSE(V4_8, u); +DECL_UNPACK_TABLE_SSE(V4_16, s); +DECL_UNPACK_TABLE_SSE(V4_8, s); +DECL_UNPACK_TABLE_SSE(V4_5, u); + +static const VIFSSEUnpackTable VIFfuncTableSSE[16] = { + { _UNPACK_TABLE_SSE(S_32, u), _UNPACK_TABLE_SSE(S_32, u) }, + { _UNPACK_TABLE_SSE(S_16, u), _UNPACK_TABLE_SSE(S_16, s) }, + { _UNPACK_TABLE_SSE(S_8, u), _UNPACK_TABLE_SSE(S_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V2_32, u), _UNPACK_TABLE_SSE(V2_32, u) }, + { _UNPACK_TABLE_SSE(V2_16, u), _UNPACK_TABLE_SSE(V2_16, s) }, + { _UNPACK_TABLE_SSE(V2_8, u), _UNPACK_TABLE_SSE(V2_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V3_32, u), _UNPACK_TABLE_SSE(V3_32, u) }, + { _UNPACK_TABLE_SSE(V3_16, u), _UNPACK_TABLE_SSE(V3_16, s) }, + { _UNPACK_TABLE_SSE(V3_8, u), _UNPACK_TABLE_SSE(V3_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V4_32, u), _UNPACK_TABLE_SSE(V4_32, u) }, + { _UNPACK_TABLE_SSE(V4_16, u), _UNPACK_TABLE_SSE(V4_16, s) }, + { _UNPACK_TABLE_SSE(V4_8, u), _UNPACK_TABLE_SSE(V4_8, s) }, + { _UNPACK_TABLE_SSE(V4_5, u), _UNPACK_TABLE_SSE(V4_5, u) }, +}; + +#endif + + +void vif0FLUSH(); +void vif1FLUSH(); + +void vifDmaInit() { +} + +__inline static int _limit( int a, int max ) { + return ( a > max ? max : a ); +} + +static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdmanum) { + u32 *dest; + unsigned int unpackType; + UNPACKFUNCTYPE func; + UNPACKPARTFUNCTYPE funcP; + const VIFUnpackFuncTable *ft; + vifStruct *vif; + VIFregisters *vifRegs; + VURegs * VU; + u8 *cdata = (u8*)data; + int memsize; + + _mm_prefetch((char*)data, _MM_HINT_NTA); + + if (VIFdmanum == 0) { + VU = &VU0; + vif = &vif0; + vifRegs = vif0Regs; + memsize = 0x1000; + assert( v->addr < 0x4000 ); + v->addr &= 0xfff; + } else { + VU = &VU1; + vif = &vif1; + vifRegs = vif1Regs; + memsize = 0x4000; + v->addr &= 0x3fff; + } + + dest = (u32*)(VU->Mem + v->addr); + +#ifdef VIF_LOG + VIF_LOG("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); +#endif + +/* if (vifRegs->cycle.cl > vifRegs->cycle.wl) { + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + }*/ +#ifdef _DEBUG + if (v->size != size) { +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: warning v->size != size\n"); +#endif + } + if ((v->addr+size*4) > memsize) { + SysPrintf("*PCSX2*: fixme unpack overflow\n"); + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + } +#endif + + if (size == 0) { + //SysPrintf("*PCSX2*: Unpack with size 0!!\n"); + return; + } + + // The unpack type + unpackType = v->cmd & 0xf; + + if(unpackType == 0xC && vifRegs->mode == 0 && !(vifRegs->code & 0x10000000) && vifRegs->cycle.cl == vifRegs->cycle.wl) { + // v4-32 + memcpy_amd((u8*)dest, cdata, size << 2); + size = 0; + return; + } + + _mm_prefetch((char*)data+128, _MM_HINT_NTA); + _vifRegs = (VIFregisters*)vifRegs; + _vifMaskRegs = VIFdmanum ? g_vif1Masks : g_vif0Masks; + _vif = vif; + _vifRow = VIFdmanum ? g_vifRow1 : g_vifRow0; + + // Unpacking + vif->wl = 0; vif->cl = 0; + //memsize = size; + size*= 4; + if (vifRegs->cycle.cl >= vifRegs->cycle.wl) { // skipping write + + if( !(v->addr&0xf) && cpucaps.hasStreamingSIMD2Extensions ) { + const UNPACKPARTFUNCTYPE* pfn; + int writemask; + //static LARGE_INTEGER lbase, lfinal; + //QueryPerformanceCounter(&lbase); + u32 oldcycle = -1; + FreezeXMMRegs(1); + +// u16 tempdata[4] = { 0x8000, 0x7fff, 0x1010, 0xd0d0 }; +// vifRegs->cycle.cl = 4; +// vifRegs->cycle.wl = 1; +// SetNewMask(g_vif1Masks, g_vif1HasMask3, 0x3f, ~0x3f); +// memset(dest, 0xcd, 64*4); +// VIFfuncTableSSE[1].funcS[6](dest, (u32*)tempdata, 8); + + if( VIFdmanum ) { + __asm movaps XMM_ROW, qword ptr [g_vifRow1] + __asm movaps XMM_COL, qword ptr [g_vifCol1] + } + else { + __asm movaps XMM_ROW, qword ptr [g_vifRow0] + __asm movaps XMM_COL, qword ptr [g_vifCol0] + } + + if( vifRegs->cycle.cl == 0 || vifRegs->cycle.wl == 0 || (vifRegs->cycle.cl == vifRegs->cycle.wl && !(vifRegs->code&0x10000000)) ) { + oldcycle = *(u32*)&vifRegs->cycle; + vifRegs->cycle.cl = vifRegs->cycle.wl = 1; + } + + pfn = vif->usn ? VIFfuncTableSSE[unpackType].funcU: VIFfuncTableSSE[unpackType].funcS; + writemask = VIFdmanum ? g_vif1HasMask3[min(vifRegs->cycle.wl-1,3)] : g_vif0HasMask3[min(vifRegs->cycle.wl-1,3)]; + writemask = pfn[(((vifRegs->code & 0x10000000)>>28)<mode](dest, (u32*)cdata, size); + + if( oldcycle != -1 ) *(u32*)&vifRegs->cycle = oldcycle; + + // if size is left over, update the src,dst pointers + if( writemask > 0 ) { + int left; + ft = &VIFfuncTable[ unpackType ]; + left = (size-writemask)/ft->qsize; + cdata += size-writemask; + dest = (u32*)((u8*)dest + ((left/vifRegs->cycle.wl)*vifRegs->cycle.cl + left%vifRegs->cycle.wl)*16); + } + + size = writemask; + + //QueryPerformanceCounter(&lfinal); + //((LARGE_INTEGER*)g_nCounters)->QuadPart += lfinal.QuadPart - lbase.QuadPart; + } + else { + int incdest, wl, chans; + ft = &VIFfuncTable[ unpackType ]; + // Assigning the normal upack function, the part type is assigned later + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + 4; + wl = vifRegs->cycle.wl-1; + chans = (ft->qsize/ft->dsize)*ft->gsize; + + //SysPrintf("slow vif\n"); + + while (size >= ft->qsize) { + funcP( dest, (u32*)cdata, chans); + cdata += ft->qsize; + size -= ft->qsize; + + if (vif->cl >= wl) { + dest += incdest; + vif->cl = 0; + } + else { + dest += 4; + vif->cl++; + } + } + } + + // used for debugging vif +// { +// int i, j; +// u32* curdest = (u32*)(VU->Mem + v->addr); +// FILE* ftemp = fopen("temp.txt", "a+"); +// fprintf(ftemp, "%x %x %x\n", vifRegs->code>>24, vifRegs->mode, *(u32*)&vifRegs->cycle); +// +// +// for(i = 0; i < memsize; ) { +// for(j = 0; j <= ((vifRegs->code>>26)&3); ++j) { +// fprintf(ftemp, "%x ", curdest[j]); +// } +// fprintf(ftemp, "\n"); +// curdest += 4*vifRegs->cycle.cl; +// i += j; +// } +// fclose(ftemp); +// } + +#ifdef VIF_LOG + VIF_LOG("remaining %d\n", size); +#endif + + if( size > 0 ) { +#ifdef VIF_LOG + VIF_LOG("warning, end with size = %d\n", size); +#endif + // SSE doesn't handle such small data + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + while (size >= ft->dsize) { + if (vif->cl < vifRegs->cycle.wl) { /* unpack one qword */ + size-= funcP(dest, (u32*)cdata, (size/ft->dsize)*ft->gsize); + break; + } + dest += 4; + vif->cl++; + if (vif->cl == vifRegs->cycle.cl) { + vif->cl = 0; + } + } + } + } else + if (vifRegs->cycle.cl < vifRegs->cycle.wl) { /* filling write */ +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: filling write\n"); +#endif + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + SysPrintf("filling write\n"); + + while (size >= ft->bsize) { + if (vif->wl == vifRegs->cycle.wl) { + vif->wl = 0; + } + func(dest, (u32*)cdata); + if (vif->wl < vifRegs->cycle.cl) { /* unpack one qword */ + cdata += ft->bsize; + size -= ft->bsize; + vif->cl++; + if (vif->cl == vifRegs->cycle.cl) { + vif->cl = 0; + } + } + dest += 4; + vif->wl++; + } + } else { + + // why is this code here? + assert(0); +// while ( size >= ft->bsize ) { +// func(dest, (u32*)cdata); +// dest += 12; +// cdata += ft->bsize; +// size -= ft->bsize; +// vif->cl++; vif->wl++; +// if (vif->cl == vifRegs->cycle.cl) { +// vif->cl = 0; +// } +// if (vif->wl == vifRegs->cycle.wl) { +// vif->wl = 0; +// } +// } +// while (size >= ft->dsize) { +// if (vif->cl < vifRegs->cycle.wl) { /* unpack one qword */ +// funcP(dest, (u32*)cdata, (size/ft->dsize)*ft->gsize); +// break; +// } +// dest += 4; +// vif->cl++; +// if (vif->cl == vifRegs->cycle.cl) { +// vif->cl = 0; +// } +// } + } + + if (size > 0) { +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: warning size(%d) > 0 after unpack\n", size); +#endif + } +} + +static void vuExecMicro( u32 addr, const unsigned int VIFdmanum ) { + + VURegs * VU; + //void (*_vuExecMicro)(); + +// MessageBox(NULL, "3d doesn't work\n", "Query", MB_OK); +// return; + + if (VIFdmanum == 0) { + //_vuExecMicro = Cpu->ExecuteVU0Block; + VU = &VU0; + vif0FLUSH(); + } else { + //_vuExecMicro = Cpu->ExecuteVU1Block; + VU = &VU1; + vif1FLUSH(); + } + + VU->vifRegs->itop = VU->vifRegs->itops; + + if (VIFdmanum == 1) { + /* in case we're handling a VIF1 execMicro + set the top with the tops value */ + VU->vifRegs->top = VU->vifRegs->tops; + + /* is DBF flag set in VIF_STAT? */ + if (VU->vifRegs->stat & 0x80) { + /* it is, so set tops with base + ofst + and clear stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base; + VU->vifRegs->stat &= ~0x80; + } else { + /* it is not, so set tops with base + and set the stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst; + VU->vifRegs->stat |= 0x80; + } + } + + if (VIFdmanum == 0) { + vu0ExecMicro(addr); + } else { + vu1ExecMicro(addr); + } +} + +void vif0Init() { + u32 i; + extern u8 s_maskwrite[256]; + + for(i = 0; i < 256; ++i ) { + s_maskwrite[i] = ((i&3)==3)||((i&0xc)==0xc)||((i&0x30)==0x30)||((i&0xc0)==0xc0); + } + + SetNewMask(g_vif0Masks, g_vif0HasMask3, 0, 0xffffffff); +} + +void vif0FLUSH() { + int _cycles; + _cycles = VU0.cycle; + + vu0Finish(); + cycles+= (VU0.cycle - _cycles)*BIAS; +} + +void vif0UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + vif0FLUSH(); + + vl = (vif0.cmd ) & 0x3; + vn = (vif0.cmd >> 2) & 0x3; + vif0.tag.addr = (data[0] & 0x3ff) << 4; + vif0.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + + if ( vif0Regs->cycle.wl <= vif0Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif0Regs->cycle.cl * (vifNum / vif0Regs->cycle.wl) + + _limit( vifNum % vif0Regs->cycle.wl, vif0Regs->cycle.cl ); + + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + + vif0.tag.cmd = vif0.cmd; + vif0.tag.size = len; + vif0Regs->offset = 0; +} + +void _vif0mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif0mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU0.Micro + addr, data, size << 2)) { + memcpy_amd(VU0.Micro + addr, data, size << 2); + Cpu->ClearVU0(addr, size); + } +} + +int vif0transferData(u32 *data, int size) { + int ret=0; + +#ifdef VIF_LOG + VIF_LOG("VIFtransferData: cmd %x, size %x, vif0.tag.size %x\n", vif0.cmd, size, vif0.tag.size); +#endif + if ((vif0.cmd & 0x60) == 0x60) { // UNPACK +#ifdef VIF_LOG + VIF_LOG("UNPACKData: cmd %x, size %x, vif0.tag.size %x\n", vif0.cmd, size, vif0.tag.size); +#endif + if (size < vif0.tag.size) { + VIFunpack(data, &vif0.tag, size, VIF0dmanum); + // cycles+= size >> 1; + vif0.tag.addr += size << 2; + vif0.tag.size -= size; + ret = size; + } else { + VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + // cycles+= vif0.tag.size >> 1; + ret = vif0.tag.size; + vif0.tag.size = 0; + } + } else { + switch (vif0.cmd) { + case 0x20: // STMASK + SetNewMask(g_vif0Masks, g_vif0HasMask3, data[0], vif0Regs->mask); + vif0Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif0Regs->mask); +#endif + ret = 1; + vif0.tag.size = 0; + break; + + case 0x30: // STROW + { + u32* pmem = &vif0Regs->r0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifRow0+vif0.tag.addr; + assert( vif0.tag.addr < 4 ); + ret = min(4-vif0.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[3] = data[3]; pmem2[3] = data[3]; + case 3: pmem[2] = data[2]; pmem2[2] = data[2]; + case 2: pmem[1] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + break; + } + case 0x31: // STCOL + { + u32* pmem = &vif0Regs->c0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifCol0+vif0.tag.addr; + ret = min(4-vif0.tag.addr, size); + switch(ret) { + case 4: pmem[3] = data[3]; pmem2[3] = data[3]; + case 3: pmem[2] = data[2]; pmem2[2] = data[2]; + case 2: pmem[1] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + break; + } + case 0x4A: // MPG + if (size < vif0.tag.size) { + _vif0mpgTransfer(vif0.tag.addr, data, size); + vif0.tag.addr += size << 2; + vif0.tag.size -= size; + ret = size; + } else { + _vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size); + ret = vif0.tag.size; + vif0.tag.size = 0; + } + break; + } + } + if (vif0.tag.size <= 0) { + vif0.cmd = 0; + } + + return ret; +} + +void vif0CMD(u32 *data, int size) { + int vifNum; + + switch ( vif0.cmd & 0x7F ) { + case 0x00: // NOP + vif0.cmd = 0; + break; + + case 0x01: // STCYCL + vif0Regs->cycle.cl = data[0] & 0xff; + vif0Regs->cycle.wl = (data[0] >> 8) & 0xff; + vif0.cmd = 0; + break; + + case 0x04: // ITOP + vif0Regs->itops = data[0] & 0x3ff; + vif0.cmd = 0; + break; + + case 0x05: // STMOD + vif0Regs->mode = data[0] & 0x3; + vif0.cmd = 0; + break; + + case 0x07: // MARK + vif0Regs->mark = (u16)data[0]; + vif0Regs->stat |= VIF0_STAT_MRK; + vif0.cmd = 0; + break; + + case 0x10: // FLUSHE + vif0FLUSH(); + vif0.cmd = 0; + break; + + case 0x14: // MSCAL + case 0x15: // MSCALF + vuExecMicro( (u16)( data[0]) << 3, VIF0dmanum ); + vif0.cmd = 0; + break; + + case 0x17: // MSCNT + vuExecMicro( -1, VIF0dmanum ); + vif0.cmd = 0; + break; + + case 0x20: // STMASK + break; + + case 0x30: // STROW + vif0.tag.addr = 0; + vif0.tag.size = 4; + break; + + case 0x31: // STCOL + vif0.tag.addr = 0; + vif0.tag.size = 4; + break; + + case 0x4A: // MPG + vif0FLUSH(); + vifNum = (data[0] >> 16) & 0xff; + if (vifNum == 0) vifNum = 256; + vif0.tag.addr = (u16)(data[0]) << 3; + vif0.tag.size = vifNum << 1; + break; + + default: + vif0.cmd = 0; + if ((vif0Regs->err & 0x6) == 0) { //Mask Vifcode and DMA tag mismatch errors + SysPrintf( "UNKNOWN VifCmd: %x\n", vif0.cmd ); + vif0Regs->stat |= 1 << 13; + } + break; + } +} + +int VIF0transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif0.vifstalled ? vif0.irqoffset : 0; + +#ifdef VIF_LOG + VIF_LOG( "VIF0transfer: size %x (vif0.cmd %x)\n", size, vif0.cmd ); +#endif + +/* { + int i; + for (i=0; i 0) { + + if (vif0.cmd) { + //vif0Regs->stat |= VIF0_STAT_VPS_T; + ret = vif0transferData(data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif0Regs->stat &= ~VIF0_STAT_VPS_T; + continue; + } + + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + vif0.cmd = (data[0] >> 24); + vif0Regs->code = data[0]; + if(vif0.irq && vif0.cmd != 0x7/* && size > 1*/) { + break; + } + +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + + if ((vif0.cmd & 0x80) && !(vif0Regs->err & 0x1)) { //i bit on vifcode and not masked by VIF0_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif0.cmd, psHu32(INTC_MASK) ); +#endif + vif0.irq++; + } + + //vif0Regs->stat |= VIF0_STAT_VPS_D; + if ((vif0.cmd & 0x60) == 0x60) { + vif0UNPACK(data); + } else { + vif0CMD(data, size); + } + //vif0Regs->stat &= ~VIF0_STAT_VPS_D; + if(vif0.tag.size > 0) vif0Regs->stat |= VIF0_STAT_VPS_W; + data++; + size--; + transferred++; + + } + + if( !vif0.cmd ) + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + if (vif0.irq > 0) { + vif0.irq--; + + if( istag ) { + hwIntcIrq(VIF0intc); + vif0Regs->stat|= VIF0_STAT_INT; + return -2; + } + + vif0.irqoffset = transferred%4; // cannot lose the offset + + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + //SysPrintf("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + hwIntcIrq(VIF0intc); + vif0Regs->stat|= VIF0_STAT_INT; + //if(size > 0) SysPrintf("VIF0 Remaining size %x, data %x_%x_%x_%x\n", size, data[3], data[2], data[1], data[0]); + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + } + + return 0; +} + +int _VIF0chain() { + u32 *pMem; + u32 qwc = vif0ch->qwc; + u32 ret; + + if (vif0ch->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif0ch->madr); + if (pMem == NULL) { + SysPrintf("VIF0chain bad madr %x", vif0ch->madr); + return -1; + } + + if( vif0.vifstalled ) { + ret = VIF0transfer(pMem+vif0.irqoffset, vif0ch->qwc*4-vif0.irqoffset, 0); + } + else { + ret = VIF0transfer(pMem, vif0ch->qwc*4, 0); + } + cycles+= (qwc-vif0ch->qwc)*BIAS; /* guessing */ + return ret; +} + +int _chainVIF0() { + u32 *ptag; + int id; + int done=0; + int ret; + + ptag = (u32*)dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + } + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif0ch->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + vif0ch->madr = ptag[1]; //MADR = ADDR field + cycles+=1; // Add 1 cycles from the QW read for the tag +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[0], ptag[1], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr); +#endif + + vif0ch->chcr = ( vif0ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + done |= hwDmacSrcChainWithStack(vif0ch, id); + if (vif0ch->chcr & 0x40) { + ret = VIF0transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -1) + return -1; //There has been an error + if (ret == -2) { + vif0.vifstalled = 1; + return done; //IRQ set by VIFTransfer + } + } + + ret = _VIF0chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + vif0.vifstalled = 1; + return done; + } + + //if(id == 7)vif0ch->tadr = vif0ch->madr; + + vif0.vifstalled = 0; + + if ((vif0ch->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF0 TIE\n"); + //SysPrintf( "VIF0dmaIrq Set\n" ); + vif0ch->qwc = 0; + vif0Regs->stat|= VIF0_STAT_VIS; //Set the Tag Interrupt flag of VIF0_STAT + return 1; //End Transfer + } + return done; //Return Done +} + +int vif0Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif0Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + // need to check DMAC_CTRL + if ((vif0ch->chcr & 0x4) && vif0.done == 0 && vif0.vifstalled == 0 ) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif0 dma masked\n"); + return 0; + } + + cycles = 0; + ret = _chainVIF0(); + if (ret != 0) vif0.done = 1; + INT(0, cycles); + return 0; + } + if(vif0.vifstalled == 1) { + // vif0.done = 0; + return 0; + } + + // hack? + vif0.tag.size = 0; + vif0.cmd = 0; + vif0Regs->stat &= ~VIF0_STAT_VPS; + // hack? + + vif0ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF0); + vif0Regs->stat&= ~0xF000000; // FQC=0 + + return 1; +} + +void dmaVIF0() { +#ifdef VIF_LOG + VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif0ch->chcr, vif0ch->madr, vif0ch->qwc, + vif0ch->tadr, vif0ch->asr0, vif0ch->asr1 ); +#endif + /*if (vif0.irq > 0) { + vif0.irq--; + hwIntcIrq(VIF0intc); + return; + }*/ + + cycles = 0; +// if(vif0ch->qwc > 0) { +// _VIF0chain(); +// INT(0, cycles); +// } + vif0Regs->stat|= 0x8000000; // FQC=8 + + if (!(vif0ch->chcr & 0x4)) { // Normal Mode + _VIF0chain(); + INT(0, cycles); + FreezeXMMRegs(0); + FreezeMMXRegs(0); + return; + } + + if (_VIF0chain() != 0) { + INT(0, cycles); + FreezeXMMRegs(0); + FreezeMMXRegs(0); + return; + } + + // Chain Mode + vif0.done = 0; + INT(0, cycles); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif0Write32(u32 mem, u32 value) { + if (mem == 0x10003830) { // MARK + vif0Regs->stat&= ~0x40; + vif0Regs->mark = value; + } else + if (mem == 0x10003c10) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF0_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + memset(&vif0, 0, sizeof(vif0)); + vif0ch->qwc = 0; + vif0Regs->err = 0; + vif0.done = 1; + //vif0Reset(); + vif0Regs->stat&= ~0x0F000000; // FQC=0 + + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif0Regs->stat |= VIF0_STAT_VFS; + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + + vif0Regs->stat |= VIF0_STAT_VSS; + //dmaVIF0(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif0Regs->stat & (VIF0_STAT_INT|VIF0_STAT_VSS|VIF0_STAT_VIS|VIF0_STAT_VFS)) { + cancel = 1; + } + vif0Regs->stat &= ~(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS | + VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); + if (cancel) { + //SysPrintf("VIF0 Stall Resume\n"); + if( vif0.vifstalled ) { + // only reset if no further stalls + if( _VIF0chain() != -2 ) + vif0.vifstalled = 0; + } + } + INT(0,0); + } + } else + if (mem == 0x10003820) { // ERR + vif0Regs->err = value; + } + else if (mem == 0x10003800) { // STAT +#ifdef VIF_LOG + VIF_LOG("VIF0_STAT write32 0x%8.8x\n", value); +#endif +// vif0ch->qwc = 0; +// vif0.vifstalled = 0; +// vif0.done = 1; +// vif0Regs->stat&= ~0x0F000000; // FQC=0 + } + else if( mem >= 0x10003900 && mem < 0x10003980 ) { + assert( (mem&0xf) == 0 ); + if( mem < 0x10003940 ) g_vifRow0[(mem>>4)&3] = value; + else g_vifCol0[(mem>>4)&3] = value; + } +} + +void vif0Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif0, 0, sizeof(vif0)); + memset(vif0Regs, 0, sizeof(vif0Regs)); + + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif0Freeze(gzFile f, int Mode) { + gzfreeze(&vif0, sizeof(vif0)); + + if (Mode == 0) + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + +void vif1Init() { + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); +} + +void vif1FLUSH() { + int _cycles; + _cycles = VU1.cycle; + + if( VU0.VI[REG_VPU_STAT].UL & 0x100 ) { + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU1Block(); + } while(VU0.VI[REG_VPU_STAT].UL & 0x100); + +// FreezeXMMRegs(0); +// FreezeMMXRegs(0); + + cycles+= (VU1.cycle - _cycles)*BIAS; + } +} + +void vif1UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + vif1FLUSH(); + + vl = (vif1.cmd ) & 0x3; + vn = (vif1.cmd >> 2) & 0x3; + vif1.tag.addr = (data[0] & 0x3ff); + vif1.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + + if ( vif1Regs->cycle.wl <= vif1Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif1Regs->cycle.cl * (vifNum / vif1Regs->cycle.wl) + + _limit( vifNum % vif1Regs->cycle.wl, vif1Regs->cycle.cl ); + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + if ( ( data[0] >> 15) & 0x1 ) { + vif1.tag.addr += vif1Regs->tops; + } + + vif1.tag.addr <<= 4; + vif1.tag.addr &= 0x3fff; + vif1.tag.cmd = vif1.cmd; + vif1.tag.size = len; + vif1Regs->offset = 0; +} + +void _vif1mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif1mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU1.Micro + addr, data, size << 2)) { + memcpy_amd(VU1.Micro + addr, data, size << 2); + Cpu->ClearVU1(addr, size); + } +} + +int vif1transferData(u32 *data, int size) { + int ret=0; + +#ifdef VIF_LOG + VIF_LOG("VIFtransferData: cmd %x, size %x, vif1.tag.size %x\n", vif1.cmd, size, vif1.tag.size); +#endif + if ((vif1.cmd & 0x60) == 0x60) { // UNPACK +#ifdef VIF_LOG + VIF_LOG("UNPACKData: cmd %x, size %x, vif1.tag.size %x\n", vif1.cmd, size, vif1.tag.size); +#endif + if (size < vif1.tag.size) { + /* size is less that the total size, transfer is + 'in pieces' */ + VIFunpack(data, &vif1.tag, size, VIF1dmanum); + // cycles+= size >> 1; + vif1.tag.addr += size << 2; + vif1.tag.size -= size; + ret = size; + } else { + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + //cycles+= vif1.tag.size >> 1; + ret = vif1.tag.size; + vif1.tag.size = 0; + } + } else { + switch (vif1.cmd) { + case 0x20: // STMASK + SetNewMask(g_vif1Masks, g_vif1HasMask3, data[0], vif1Regs->mask); + vif1Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif1Regs->mask); +#endif + ret = 1; + vif1.tag.size = 0; + break; + + case 0x30: // STROW + { + u32* pmem = &vif1Regs->r0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifRow1+vif1.tag.addr; + assert( vif1.tag.addr < 4 ); + ret = min(4-vif1.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + break; + } + case 0x31: // STCOL + { + u32* pmem = &vif1Regs->c0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifCol1+vif1.tag.addr; + ret = min(4-vif1.tag.addr, size); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + break; + } + case 0x4A: // MPG + if (size < vif1.tag.size) { + _vif1mpgTransfer(vif1.tag.addr, data, size); + vif1.tag.addr += size << 2; + vif1.tag.size -= size; + ret = size; + } else { + _vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size); + ret = vif1.tag.size; + vif1.tag.size = 0; + } + + break; + + case 0x50: // DIRECT + case 0x51: // DIRECTHL + + if (size < vif1.tag.size) { + vif1.tag.size-= size; + ret = size; + } else { + ret = vif1.tag.size; + vif1.tag.size = 0; + } + + if( CHECK_MULTIGS ) { + u8* gsmem = GSRingBufCopy(data, ret<<2, GS_RINGTYPE_P2); + if( gsmem != NULL ) { + memcpy_amd(gsmem, data, ret<<2); + GSRINGBUF_DONECOPY(gsmem, ret<<2); + GSgifTransferDummy(1, data, ret>>2); + } + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); + } + else { +#ifdef GSCAPTURE + extern u32 g_loggs, g_gstransnum, g_gsfinalnum; + + if( !g_loggs || (g_loggs && g_gstransnum++ < g_gsfinalnum)) { + // call directly + FreezeMMXRegs(1); + FreezeXMMRegs(1); + GSgifTransfer2(data, (ret >> 2) - GSgifTransferDummy(1, data, ret>>2)); + } +#else + FreezeMMXRegs(1); + FreezeXMMRegs(1); + GSgifTransfer2(data, (ret >> 2)); +#endif + } + + //GSCSRr |= 2; // set finish? + + break; + } + } + if (vif1.tag.size <= 0) { + vif1.cmd = 0; + } + + return ret; +} + +void vif1CMD(u32 *data, int size) { + int vifNum; + int vifImm; + + switch ( vif1.cmd & 0x7F ) { + case 0x00: // NOP + vif1.cmd = 0; + break; + + case 0x01: // STCYCL + vif1Regs->cycle.cl = (u8)data[0]; + vif1Regs->cycle.wl = (u8)(data[0] >> 8); + vif1.cmd = 0; + break; + + case 0x02: // OFFSET + vif1Regs->ofst = data[0] & 0x3ff; + vif1Regs->stat &= ~0x80; + vif1Regs->tops = vif1Regs->base; + vif1.cmd = 0; + break; + + case 0x03: // BASE + vif1Regs->base = data[0] & 0x3ff; + vif1.cmd = 0; + break; + + case 0x04: // ITOP + vif1Regs->itops = data[0] & 0x3ff; + vif1.cmd = 0; + break; + + case 0x05: // STMOD + vif1Regs->mode = data[0] & 0x3; + vif1.cmd = 0; + break; + + case 0x06: // MSKPATH3 + vif1Regs->mskpath3 = (data[0] >> 15) & 0x1; + if ( vif1Regs->mskpath3 ) { + if(gif->qwc) _GIFchain(); // Finish the transfer first + psHu32(GIF_STAT) |= 0x2; + } else { + psHu32(GIF_STAT) &= ~0x2; + if(gif->qwc) _GIFchain(); // Finish the transfer first + } + vif1.cmd = 0; + break; + + case 0x07: // MARK + vif1Regs->mark = (u16)data[0]; + vif1Regs->stat |= VIF1_STAT_MRK; + vif1.cmd = 0; + break; + + case 0x10: // FLUSHE + case 0x11: // FLUSH + case 0x13: // FLUSHA + vif1FLUSH(); + vif1.cmd = 0; + break; + + case 0x14: // MSCAL + case 0x15: // MSCALF + vuExecMicro( (u16)(data[0]) << 3, VIF1dmanum ); + vif1.cmd = 0; + break; + + case 0x17: // MSCNT + vuExecMicro( -1, VIF1dmanum ); + vif1.cmd = 0; + break; + + case 0x20: // STMASK + break; + + case 0x30: // STROW + vif1.tag.addr = 0; + vif1.tag.size = 4; + break; + + case 0x31: // STCOL + vif1.tag.addr = 0; + vif1.tag.size = 4; + break; + + case 0x4A: // MPG + vif1FLUSH(); + vifNum = (u8)(data[0] >> 16); + if (vifNum == 0) vifNum = 256; + vif1.tag.addr = (u16)(data[0]) << 3; + vif1.tag.size = vifNum * 2; + break; + + case 0x50: // DIRECT + case 0x51: // DIRECTHL + vifImm = (u16)data[0]; + if (vifImm == 0) { + vif1.tag.size = 65536 << 2; + } else { + vif1.tag.size = vifImm << 2; + } + break; + + default: + vif1.cmd = 0; + if ((vif1Regs->err & 0x6) == 0) { //Ignore vifcode and tag mismatch error + SysPrintf( "UNKNOWN VifCmd: %x\n", vif1.cmd ); + vif1Regs->stat |= 1 << 13; + } + break; + } +} + + +int VIF1transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) + +#ifdef VIF_LOG + VIF_LOG( "VIF1transfer: size %x (vif1.cmd %x)\n", size, vif1.cmd ); +#endif + + //return 0; + + //vif1.irq = 0; + while (size > 0) { + + if (vif1.cmd) { + //vif1Regs->stat |= VIF1_STAT_VPS_T; + ret = vif1transferData(data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif1Regs->stat &= ~VIF1_STAT_VPS_T; + continue; + } + + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + vif1.cmd = (data[0] >> 24); + vif1Regs->code = data[0]; + if(vif1.irq && vif1.cmd != 0x7/* && size > 1*/) { + break; + } +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + + if ((vif1.cmd & 0x80) && !(vif1Regs->err & 0x1)) { //i bit on vifcode and not masked by VIF1_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif1.cmd, psHu32(INTC_MASK) ); +#endif + + //vif1Regs->stat|= VIF1_STAT_VIS; + vif1.irq++; + } + + //vif1Regs->stat |= VIF1_STAT_VPS_D; + if ((vif1.cmd & 0x60) == 0x60) { + vif1UNPACK(data); + } else { + vif1CMD(data, size); + } + //vif1Regs->stat &= ~VIF1_STAT_VPS_D; + if(vif1.tag.size > 0) vif1Regs->stat |= VIF1_STAT_VPS_W; + data++; + size--; + transferred++; + + } + + if( !vif1.cmd ) + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + if (vif1.irq > 0) { + vif1.irq--; + + if( istag ) { + hwIntcIrq(VIF1intc); + vif1Regs->stat|= VIF1_STAT_INT; + return -2; + } + + // spiderman doesn't break on qw boundaries + vif1.irqoffset = transferred%4; // cannot lose the offset + + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + //SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + hwIntcIrq(VIF1intc); + vif1Regs->stat|= VIF1_STAT_INT; + if(size > 0) { + //SysPrintf("VIF1 Remaining size %x, data %x_%x_%x_%x\n", size, data[3], data[2], data[1], data[0]); + } + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + } + + return 0; +} + +int _VIF1chain() { + u32 *pMem; + u32 qwc = vif1ch->qwc; + u32 ret; + + if (vif1ch->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) + return -1; + + if( vif1.vifstalled ) { + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + } + else { + ret = VIF1transfer(pMem, vif1ch->qwc*4, 0); + } + /*vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->qwc-= qwc;*/ + cycles+= (qwc-vif1ch->qwc)*BIAS; /* guessing */ + return ret; +} + +int _chainVIF1() { + u32 *ptag; + int id; + int done=0; + int ret; + + ptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + + } + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif1ch->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + vif1ch->madr = ptag[1]; //MADR = ADDR field + cycles+=1; // Add 1 cycles from the QW read for the tag +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + done |= hwDmacSrcChainWithStack(vif1ch, id); + if (vif1ch->chcr & 0x40) { + ret = VIF1transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -1) return -1; //There has been an error + if (ret == -2) { + vif1.vifstalled = 1; + return done; //IRQ set by VIFTransfer + } + } + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + //done |= hwDmacSrcChainWithStack(vif1ch, id); + ret = _VIF1chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + vif1.vifstalled = 1; + return done; + } + + //if(id == 7)vif1ch->tadr = vif1ch->madr; + + vif1.vifstalled = 0; + + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF1 TIE\n"); + //SysPrintf( "VIF1dmaIrq Set\n" ); + vif1ch->qwc = 0; + vif1Regs->stat|= VIF1_STAT_VIS; //Set the Tag Interrupt flag of VIF1_STAT + return 1; //End Transfer + } + return done; //Return Done +} + +int _vif1Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(vif1.vifstalled == 1) { + return 1; + } + if (vif1ch->chcr & 0x4 && vif1.done == 0 && vif1.vifstalled == 0) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif1 dma masked\n"); + return 0; + } + + cycles = 0; + ret = _chainVIF1(); + if (ret != 0) vif1.done = 1; + INT(1, cycles); + return 0; + } + + + // hack? + vif1.tag.size = 0; + vif1.cmd = 0; + vif1Regs->stat &= ~VIF1_STAT_VPS; + // hack? + + + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); + vif1Regs->stat&= ~0x1F000000; // FQC=0 + + return 1; +} + +int vif1Interrupt() { + + int ret; + + ret = _vif1Interrupt(); + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + + return ret; +} + +void _dmaVIF1() { +#ifdef VIF_LOG + VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif1ch->chcr, vif1ch->madr, vif1ch->qwc, + vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 ); +#endif + + /* Check if there is a pending irq */ + /*if (vif1.irq > 0) { + vif1.irq--; + hwIntcIrq(VIF1intc); + return; + }*/ +// if(vif1ch->qwc > 0) { +// _VIF1chain(); +// INT(1, cycles); +// } + + if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO + return; + } + +#ifdef PCSX2_DEVBUILD + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1 + SysPrintf("vif1 drain stall %d\n", (psHu32(DMAC_CTRL)>>4)&3); + //return; + } +#endif + + cycles = 0; + vif1Regs->stat|= 0x10000000; // FQC=16 + + if (!(vif1ch->chcr & 0x4)) { // Normal Mode + if ((vif1ch->chcr & 0x1)) { // to Memory + _VIF1chain(); + INT(1, cycles); + } else { // from Memory + + if( CHECK_MULTIGS ) { + u8* pMem = GSRingBufCopy(NULL, 0, GS_RINGTYPE_VIFFIFO); + assert( vif1ch->qwc < 0x10000 ); + *(u32*)(pMem-16) = GS_RINGTYPE_VIFFIFO|(vif1ch->qwc<<16); // hack + *(u32*)(pMem-12) = vif1ch->madr; + *(u32*)(pMem-8) = cpuRegs.cycle; + + GSRINGBUF_DONECOPY(pMem, 0); + SetEvent(g_hGsEvent); + } + else { + + int size; + u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) { + psHu32(DMAC_STAT)|= 1<<15; + return; + } + + if( GSreadFIFO2 == NULL ) { + for (size=vif1ch->qwc; size>0; size--) { + if (size > 1) GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + GSreadFIFO2(pMem, vif1ch->qwc); + + // set incase read + psHu64(0x5000) = pMem[2*vif1ch->qwc-2]; + psHu64(0x5008) = pMem[2*vif1ch->qwc-1]; + } + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + INT(1, cycles); + } + } + vif1.done = 1; + return; + } + +/* if (_VIF1chain() != 0) { + INT(1, cycles); + return; + }*/ + + // Chain Mode + vif1.done = 0; + INT(1, cycles); +} + +void dmaVIF1() +{ + _dmaVIF1(); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif1Write32(u32 mem, u32 value) { + if (mem == 0x10003c30) { // MARK +#ifdef VIF_LOG + VIF_LOG("VIF1_MARK write32 0x%8.8x\n", value); +#endif + /* Clear mark flag in VIF1_STAT and set mark with 'value' */ + vif1Regs->stat&= ~VIF1_STAT_MRK; + vif1Regs->mark = value; + } else + if (mem == 0x10003c10) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF1_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + //SysPrintf("Vif1 Reset\n"); + memset(&vif1, 0, sizeof(vif1)); + vif1ch->qwc = 0; //? + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->err = 0; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif1Regs->stat |= VIF1_STAT_VFS; + SysPrintf("vif1 force break\n"); + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + vif1Regs->stat |= VIF1_STAT_VSS; + //SysPrintf("Vif1 Stop\n"); + //dmaVIF1(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + cancel = 1; + } + + vif1Regs->stat &= ~(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS | + VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1); + if (cancel) { + //SysPrintf("VIF1 Stall Resume\n"); + if( vif1.vifstalled ) { + // loop necessary for spiderman + if ( _VIF1chain() != -2 ) + vif1.vifstalled = 0; + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + } + } + + INT(1, 0); // If vif is stopped/stall cancelled/ or force break, we need to make sure the dma ends. + } + } else + if (mem == 0x10003c20) { // ERR +#ifdef VIF_LOG + VIF_LOG("VIF1_ERR write32 0x%8.8x\n", value); +#endif + /* Set VIF1_ERR with 'value' */ + vif1Regs->err = value; + } else + if (mem == 0x10003c00) { // STAT +#ifdef VIF_LOG + VIF_LOG("VIF1_STAT write32 0x%8.8x\n", value); +#endif + +#ifdef PCSX2_DEVBUILD + /* Only FDR bit is writable, so mask the rest */ + if( (vif1Regs->stat & VIF1_STAT_FDR) ^ (value & VIF1_STAT_FDR) ) { + // different so can't be stalled + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + SysPrintf("changing dir when vif1 fifo stalled\n"); + } + } +#endif + + vif1Regs->stat = (vif1Regs->stat & ~VIF1_STAT_FDR) | (value & VIF1_STAT_FDR); + if (vif1Regs->stat & VIF1_STAT_FDR) { + vif1Regs->stat|= 0x01000000; + } else { + vif1ch->qwc = 0; + vif1.vifstalled = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + } + else if( mem >= 0x10003d00 && mem < 0x10003d80 ) { + assert( (mem&0xf) == 0 ); + if( mem < 0x10003d40 ) g_vifRow1[(mem>>4)&3] = value; + else g_vifCol1[(mem>>4)&3] = value; + } + + /* Other registers are read-only so do nothing for them */ +} + +void vif1Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif1, 0, sizeof(vif1)); + memset(vif1Regs, 0, sizeof(vif1Regs)); + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif1Freeze(gzFile f, int Mode) { + gzfreeze(&vif1, sizeof(vif1)); + if (Mode == 0) + SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); + + return 0; +} \ No newline at end of file diff --git a/VifDma.h b/VifDma.h new file mode 100644 index 0000000000..63087c619d --- /dev/null +++ b/VifDma.h @@ -0,0 +1,120 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIFDMA_H__ +#define __VIFDMA_H__ + +typedef struct { + int addr; + int size; + int cmd; + u16 wl; + u16 cl; +} vifCode; + +// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito +typedef struct { + vifCode tag; + int cmd; + int irq; + int cl; + int wl; + u8 usn; + u8 done; + u8 vifstalled; + u8 irqoffset; // 32bit offset where next vif code is +} vifStruct; + +vifStruct vif0; +vifStruct vif1; + +#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000]) +#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000]) + +void UNPACK_S_32( u32 *dest, u32 *data ); +int UNPACK_S_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_S_16u( u32 *dest, u32 *data ); +int UNPACK_S_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_16s( u32 *dest, u32 *data ); +int UNPACK_S_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_S_8u( u32 *dest, u32 *data ); +int UNPACK_S_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_8s( u32 *dest, u32 *data ); +int UNPACK_S_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_32( u32 *dest, u32 *data ); +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_16u( u32 *dest, u32 *data ); +int UNPACK_V2_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_16s( u32 *dest, u32 *data ); +int UNPACK_V2_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_8u( u32 *dest, u32 *data ); +int UNPACK_V2_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_8s( u32 *dest, u32 *data ); +int UNPACK_V2_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_32( u32 *dest, u32 *data ); +int UNPACK_V3_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_16u( u32 *dest, u32 *data ); +int UNPACK_V3_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_16s( u32 *dest, u32 *data ); +int UNPACK_V3_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_8u( u32 *dest, u32 *data ); +int UNPACK_V3_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_8s( u32 *dest, u32 *data ); +int UNPACK_V3_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_32( u32 *dest, u32 *data ); +int UNPACK_V4_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_16u( u32 *dest, u32 *data ); +int UNPACK_V4_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_16s( u32 *dest, u32 *data ); +int UNPACK_V4_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_8u( u32 *dest, u32 *data ); +int UNPACK_V4_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_8s( u32 *dest, u32 *data ); +int UNPACK_V4_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_5( u32 *dest, u32 *data ); +int UNPACK_V4_5part( u32 *dest, u32 *data, int size ); + +// sse1/2 + + +void vifDmaInit(); +void vif0Init(); +void vif1Init(); +int vif0Interrupt(); +int vif1Interrupt(); + +void vif0Write32(u32 mem, u32 value); +void vif1Write32(u32 mem, u32 value); + +void vif0Reset(); +void vif1Reset(); +int vif0Freeze(gzFile f, int Mode); +int vif1Freeze(gzFile f, int Mode); + +#endif diff --git a/ix86-32/iR5900Arit.c b/ix86-32/iR5900Arit.c new file mode 100644 index 0000000000..d692ea8505 --- /dev/null +++ b/ix86-32/iR5900Arit.c @@ -0,0 +1,1996 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +// NOTE: The reason ADD/SUB/etc are so large is because they are very commonly +// used and recompiler needs to cover ALL possible usages to minimize code size (zerofrog) + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#elif defined(EE_CONST_PROP) + +//// ADD +void recADD_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + g_cpuConstRegs[_Rt_].SL[0]; +} + +void recADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] ) { + u32* ptempmem; + + ptempmem = _eeGetConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(vreg) ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, mmreg, vreg); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[ creg ].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(vreg) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[creg].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)_eeGetConstReg(creg)); + PADDDMtoR(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == vreg ) { + ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( g_cpuConstRegs[ creg ].UL[0] ) + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[0] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +// s is constant +void recADD_consts(int info) +{ + recADD_constv(info, _Rs_, _Rt_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rt_); +} + +// t is constant +void recADD_constt(int info) +{ + recADD_constv(info, _Rt_, _Rs_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); +} + +// nothing is constant +void recADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PADDDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDDRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDDRtoR(EEREC_D, EEREC_S); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PADDDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( _Rd_ == _Rs_ ) { + if( _Rd_ == _Rt_ ) SHL32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 1); // mult by 2 + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + + return; + } + else if( _Rd_ == _Rt_ ) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( _Rs_ != _Rt_ ) ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else SHL32ItoR(EAX, 1); // mult by 2 + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +EERECOMPILE_CODE0(ADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// ADDU +void recADDU( void ) +{ + recADD( ); +} + +//// DADD +void recDADD_const( void ) +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ creg ].UD[0] ) { + + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDQMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + if( g_cpuConstRegs[ creg ].UD[0] ) PADDQMtoR(mmreg, (u32)_eeGetConstReg(creg)); + } + else { + + if( g_cpuConstRegs[ creg ].UL[0] == 0 && g_cpuConstRegs[ creg ].UL[1] == 0 && _hasFreeMMXreg() ) { + // copy + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + if( EEINST_ISLIVE1(_Rd_) ) MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + else { + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + if( _Rd_ == vreg ) { + + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ creg ].UL[ 0 ] || g_cpuConstRegs[ creg ].UL[ 1 ]) ) { + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + ADC32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ creg ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + } + + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32ItoR( EDX, g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDADD_consts(int info) +{ + recDADD_constv(info, _Rs_, _Rt_); +} + +void recDADD_constt(int info) +{ + recDADD_constv(info, _Rt_, _Rs_); +} + +void recDADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PADDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( _Rs_ != _Rt_ ) PADDQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else PSLLQItoR(mmreg, 1); // mult by 2 + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// DADDU +void recDADDU( void ) +{ + recDADD( ); +} + +//// SUB + +void recSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] - g_cpuConstRegs[_Rt_].SL[0]; +} + +void recSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rs_ ].UL[0] ) { + + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + } + else { + if( _Rd_ == _Rt_ ) { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) SUB32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rs_ ].UL[ 0 ]); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + NEG32R(EAX); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +void recSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rt_ ].UL[0] ) { + + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(_Rs_) ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, EEREC_S, _Rs_); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[_Rt_].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(_Rs_) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[_Rt_].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PSUBDMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == _Rs_ ) { + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +void recSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PSUBDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + info = (info&~PROCESS_EE_SET_D(0xf))|PROCESS_EE_SET_D(t0reg); + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBDRtoR(EEREC_D, EEREC_T); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_)) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PSUBDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( !EEINST_ISLIVE1(_Rd_) ) { + if( _Rd_ == _Rs_) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SUBU +void recSUBU( void ) +{ + recSUB( ); +} + +//// DSUB +void recDSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] - g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rs_ ].UD[0] ) { + + // flush + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (u32)_eeGetConstReg(_Rs_)); + PSUBQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] || g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoR( EDX, g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + else { + + if( _Rd_ == _Rt_ ) { + // negate _Rt_ all in memory + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + NEG32M((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADC32ItoR(EDX, 0); + NEG32R(EDX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + } + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + // take negative of 64bit number + NEG32R(EAX); + + if( EEINST_ISLIVE1(_Rd_) ) { + ADC32ItoR(EDX, 0); + NEG32R(EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rt_ ].UD[0] ) { + + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( g_cpuConstRegs[_Rt_].UD[0] ) PSUBQMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + + if( _Rd_ == _Rs_ ) { + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ]) ) { + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + SBB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ) { + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32ItoR( EDX, g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PSUBQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBQRtoR(EEREC_D, EEREC_T); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[ 0 ]); + PSUBQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( _Rd_ == _Rs_ ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DSUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSUBU +void recDSUBU( void ) +{ + recDSUB( ); +} + +//// AND +void recAND_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & g_cpuConstRegs[_Rt_].UD[0]; +} + +void recAND_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PANDMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + PXORRtoR(EEREC_D, EEREC_D); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PANDMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + else { + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + + if( _Rd_ == vreg ) { + AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] != 0xffffffff ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + AND32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) + AND32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ], 0); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recAND_consts(int info) +{ + recAND_constv(info, _Rs_, _Rt_); +} + +void recAND_constt(int info) +{ + recAND_constv(info, _Rt_, _Rs_); +} + +void recLogicalOp(int info, int op) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( EEREC_D == EEREC_S ) LogicalOpRtoR(EEREC_D, EEREC_T, op); + else if( EEREC_D == EEREC_T ) LogicalOpRtoR(EEREC_D, EEREC_S, op); + else { + MOVQRtoR(EEREC_D, EEREC_S); + LogicalOpRtoR(EEREC_D, EEREC_T, op); + } + } + else if( (g_pCurInstInfo->regs[_Rs_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + int rsreg, rtreg, rdreg; + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + rsreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + rtreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + SetMMXstate(); + + if( rdreg == rsreg ) { + if( rtreg >= 0 ) LogicalOpRtoR(rdreg, rtreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ], op); + } + else { + if( rdreg != rtreg ) { + if( rtreg >= 0 ) MOVQRtoR(rdreg, rtreg); + else MOVQMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ]); + } + + if( rsreg >= 0 ) LogicalOpRtoR(rdreg, rsreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rs_ ], op); + } + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX, op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ] + 4, EDX, op ); + if( op == 3 ) { + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]+4); + } + + if( !EEINST_ISLIVE1(_Rd_) ) EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ] + 4 ); + LogicalOp32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ], op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ] + 4, op ); + + if( op == 3 ) { + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + } + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } +} + +void recAND_(int info) +{ + recLogicalOp(info, 0); +} + +EERECOMPILE_CODE0(AND, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// OR +void recOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]; +} + +void recOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recOR_consts(int info) +{ + recOR_constv(info, _Rs_, _Rt_); +} + +void recOR_constt(int info) +{ + recOR_constv(info, _Rt_, _Rs_); +} + +void recOR_(int info) +{ + recLogicalOp(info, 1); +} + +EERECOMPILE_CODE0(OR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// XOR +void recXOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ g_cpuConstRegs[_Rt_].UD[0]; +} + +void recXOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PXORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PXORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) XOR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) XOR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recXOR_consts(int info) +{ + recXOR_constv(info, _Rs_, _Rt_); +} + +void recXOR_constt(int info) +{ + recXOR_constv(info, _Rt_, _Rs_); +} + +void recXOR_(int info) +{ + recLogicalOp(info, 2); +} + +EERECOMPILE_CODE0(XOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// NOR +void recNOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] =~(g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]); +} + +void recNOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + + // take the NOT + PCMPEQDRtoR( t0reg,t0reg); + PXORRtoR( EEREC_D,t0reg); + _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PCMPEQDRtoR( t0reg,t0reg); + if( g_cpuConstRegs[ creg ].UD[0] ) PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + + // take the NOT + PXORRtoR( rdreg,t0reg); + + _freeMMXreg(t0reg); + } + else { + if( _Rd_ == vreg ) { + NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[1]); + + if( g_cpuConstRegs[creg].UL[0] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], ~g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], ~g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recNOR_consts(int info) +{ + recNOR_constv(info, _Rs_, _Rt_); +} + +void recNOR_constt(int info) +{ + recNOR_constv(info, _Rt_, _Rs_); +} + +void recNOR_(int info) +{ + recLogicalOp(info, 3); +} + +EERECOMPILE_CODE0(NOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SLT - test with silent hill, lemans +void recSLT_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < g_cpuConstRegs[_Rt_].SD[0]; +} + +static u32 s_sltconst = 0x80000000; +static u32 s_sltconst64[2] = {0, 0x80000000}; +u32 s_sltone = 1; + +void recSLTs_consts(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( g_cpuConstRegs[_Rs_].UL[1] == (g_cpuConstRegs[_Rs_].SL[0]<0?0xffffffff:0) && EEINST_ISSIGNEXT(_Rt_) ) { + // just compare the lower values + if( sign ) { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rs_].UL[0]^0x80000000; + ptempmem[1] = 0; + + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORMtoR(EEREC_D, (u32)&s_sltconst); + } + + PCMPGTDMtoR(EEREC_D, (u32)ptempmem); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + + // fall through + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + } + } + + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + j8Ptr[1] = JBE8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +// SLT with one operand coming from mem (compares only low 32 bits) +void recSLTmemconstt(int regd, int regs, u32 mem, int sign) +{ + // just compare the lower values + int t0reg; + + if( sign ) { + if( regd == regs ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, mem); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQMtoR(regd, mem); + PCMPGTDRtoR(regd, regs); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + } + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( regd == regs ) { + MOVQMtoR(t0reg, mem); + PXORMtoR(regs, (u32)&s_sltconst); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQRtoR(t0reg, regs); + MOVQMtoR(regd, mem); + PXORMtoR(t0reg, (u32)&s_sltconst); + PCMPGTDRtoR(regd, t0reg); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + _freeMMXreg(t0reg); + } + } +} + +void recSLTs_constt(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( EEINST_ISSIGNEXT(_Rs_) && g_cpuConstRegs[_Rt_].UL[1] == (g_cpuConstRegs[_Rt_].SL[0]<0?0xffffffff:0) ) { + // just compare the lower values + if( sign ) { + recSLTmemconstt(EEREC_D, EEREC_S, (u32)_eeGetConstReg(_Rt_), 1); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rt_].UL[0]^0x80000000; + ptempmem[1] = 0; + + recSLTmemconstt(EEREC_D, EEREC_S, (u32)ptempmem, 0); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + + // fall through + } + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLTs_(int info, int sign) +{ + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLT_consts(int info) +{ + recSLTs_consts(info, 1); +} + +void recSLT_constt(int info) +{ + recSLTs_constt(info, 1); +} + +void recSLT_(int info) +{ + int t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 1); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 1); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + // just compare the lower values + if( EEREC_D == EEREC_S ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + PCMPGTDRtoR(t0reg, EEREC_S); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDRtoR(EEREC_D, EEREC_S); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } +} + +EERECOMPILE_CODE0(SLT, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +// SLTU - test with silent hill, lemans +void recSLTU_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < g_cpuConstRegs[_Rt_].UD[0]; +} + +void recSLTU_consts(int info) +{ + recSLTs_consts(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_constt(int info) +{ + recSLTs_constt(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_(int info) +{ + int t1reg; + + assert( !(info & PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 0); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 0); + return; + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOVDMtoMMX(t1reg, (u32)&s_sltconst); + + if( EEREC_D == EEREC_S ) { + PXORRtoR(EEREC_S, t1reg); + PXORRtoR(t1reg, EEREC_T); + PCMPGTDRtoR(t1reg, EEREC_S); + + PUNPCKLDQRtoR(t1reg, t1reg); + PSRLQItoR(t1reg, 63); + + // swap regs + mmxregs[t1reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(t1reg, EEREC_S); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORRtoR(EEREC_D, t1reg); + PXORRtoR(t1reg, EEREC_S); + } + + PCMPGTDRtoR(EEREC_D, t1reg); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + + _freeMMXreg(t1reg); + } +} + +EERECOMPILE_CODE0(SLTU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) +{ + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) +{ + if ( ! _Rd_ ) + { + return; + } + if ( ( _Rt_ == 0 ) || ( _Rs_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PANDRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + +} + +//////////////////////////////////////////////////// +void recOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0x0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0x0 ); + } + else if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PORRtoR( MM0, MM1 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recXOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0x0); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0x0); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recNOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0xffffffff); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0xffffffff); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PORMtoR( MM0,(int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +// test with silent hill, lemans +void recSLT( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JG8( 0 ); + j8Ptr[2] = JL8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) +{ + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JA8( 0 ); + j8Ptr[2] = JB8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +#endif diff --git a/ix86-32/iR5900Arit.h b/ix86-32/iR5900Arit.h new file mode 100644 index 0000000000..5fcd64d767 --- /dev/null +++ b/ix86-32/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/ix86-32/iR5900AritImm.c b/ix86-32/iR5900AritImm.c new file mode 100644 index 0000000000..8a075aeed0 --- /dev/null +++ b/ix86-32/iR5900AritImm.c @@ -0,0 +1,659 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#elif defined(EE_CONST_PROP) + +//// ADDI +void recADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + _Imm_; +} + +void recADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rs_); + + if( info & PROCESS_EE_MMX ) { + if( _Imm_ != 0 ) { + + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDDMtoR(EEREC_T, (u32)ptempmem); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + + if( EEINST_ISLIVE1(_Rt_) ) + _signExtendGPRMMXtoMMX(EEREC_T, _Rt_, EEREC_S, _Rs_); + else + EEINST_RESETHASLIVE1(_Rt_); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && (_Rt_ != _Rs_) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + if( _Imm_ != 0 ) { + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDDMtoR(rtreg, (u32)ptempmem); + + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + } + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, ADDI); + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + _Imm_; +} + +void recDADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( _Imm_ != 0 ) { + + // flush + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDQMtoR(EEREC_T, (u32)ptempmem); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int rtreg; + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDQMtoR(rtreg, (u32)ptempmem); + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + ADC32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], _Imm_<0?0xffffffff:0); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + ADC32ItoR( EDX, _Imm_ < 0?0xffffffff:0); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, DADDI); + +//// DADDIU +void recDADDIU( void ) +{ + recDADDI( ); +} + +//// SLTIU +void recSLTIU_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < (u64)(_Imm_); +} + +extern void recSLTmemconstt(int regd, int regs, u32 mem, int sign); +extern u32 s_sltone; + +void recSLTIU_(int info) +{ + if( info & PROCESS_EE_MMX ) { + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = ((s32)(_Imm_))^0x80000000; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 0); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTIU); + +//// SLTI +void recSLTI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < (s64)(_Imm_); +} + +void recSLTI_(int info) +{ + if( info & PROCESS_EE_MMX) { + + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = _Imm_; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 1); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + // test silent hill if modding + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTI); + +//// ANDI +void recANDI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & (s64)_ImmU_; +} + +extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +extern void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +extern void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoM(u32 to, u32 from, int op); + +void recLogicalOpI(int info, int op) +{ + if( info & PROCESS_EE_MMX ) { + SetMMXstate(); + + if( _ImmU_ != 0 ) { + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + LogicalOpMtoR(EEREC_T, (u32)ptempmem, op); + } + else { + if( op == 0 ) PXORRtoR(EEREC_T, EEREC_T); + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && ((_Rt_ != _Rs_) || (_ImmU_==0)) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + u32* ptempmem; + + SetMMXstate(); + + ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( op == 0 ) { + if ( _ImmU_ != 0 ) { + if( _ImmU_ == 0xffff ) { + // take a shortcut + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] - 2); + PSRLDItoR(rtreg, 16); + } + else { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PANDMtoR(rtreg, (u32)ptempmem); + } + } + else PXORRtoR(rtreg, rtreg); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if ( _ImmU_ != 0 ) LogicalOpMtoR(rtreg, (u32)ptempmem, op); + } + } + else { + if ( _ImmU_ != 0 ) + { + if( _Rt_ == _Rs_ ) { + LogicalOp32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_, op); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + LogicalOp32ItoR( EAX, _ImmU_, op); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + + if( op == 0 ) { + if( EEINST_ISLIVE1(_Rt_ ) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + } + else + { + if( op == 0 ) { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + } + else { + if( _Rt_ != _Rs_ ) { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + } + + if( !EEINST_ISLIVE1(_Rt_) ) EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +void recANDI_(int info) +{ + recLogicalOpI(info, 0); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ANDI); + +//////////////////////////////////////////////////// +void recORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | (s64)_ImmU_; +} + +void recORI_(int info) +{ + recLogicalOpI(info, 1); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ORI); + +//////////////////////////////////////////////////// +void recXORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ (s64)_ImmU_; +} + +void recXORI_(int info) +{ + recLogicalOpI(info, 2); +} + +EERECOMPILE_CODEX(eeRecompileCode1, XORI); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) +{ +#ifdef __x86_64_ + if ( ! _Rt_ ) + { + return; + } + + MOV64MtoR( RAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); +#else + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + if ( _Imm_ < 0 ) + { + ADC32ItoR( EDX, 0xffffffff ); + } + else + { + ADC32ItoR( EDX, 0 ); + } + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + return; + + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + return; + + // test silent hill if modding + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recANDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + if ( _ImmU_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } + +} + +//////////////////////////////////////////////////// +static u64 _imm = 0; // temp immediate + +void recORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recXORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PXORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ], MM0 ); + SetMMXstate(); +} + +#endif diff --git a/ix86-32/iR5900AritImm.h b/ix86-32/iR5900AritImm.h new file mode 100644 index 0000000000..4bd7a0c6bf --- /dev/null +++ b/ix86-32/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/ix86-32/iR5900Branch.c b/ix86-32/iR5900Branch.c new file mode 100644 index 0000000000..75faf79fc2 --- /dev/null +++ b/ix86-32/iR5900Branch.c @@ -0,0 +1,1087 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + +#if defined(EE_CONST_PROP) + +void recSetBranchEQ(int info, int bne, int process) +{ + if( info & PROCESS_EE_MMX ) { + int t0reg; + + SetMMXstate(); + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + if( t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + PCMPEQDRtoR(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + PCMPEQDRtoR(t0reg, EEREC_S); + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PCMPEQDRtoR(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + + PMOVMSKBMMXtoR(EAX, t0reg); + + _eeFlushAllUnused(); + + CMP8ItoR( EAX, 0xff ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( info & PROCESS_EE_XMM ) { + int t0reg; + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + + if( t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeXMMreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _eeFlushAllUnused(); + + AND8ItoR(EAX, 3); + CMP8ItoR( EAX, 0x3 ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + + _eeFlushAllUnused(); + + if( bne ) { + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + + x86SetJ8( j8Ptr[0] ); + } + else { + // beq + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +void recSetBranchL(int ltz) +{ + int regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + PXORRtoR(t0reg, t0reg); + PCMPGTDRtoR(t0reg, regs); + PMOVMSKBMMXtoR(EAX, t0reg); + + _freeMMXreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 0x80 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, regs); + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _freeXMMreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 2 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + if( ltz ) j32Ptr[ 0 ] = JGE32( 0 ); + else j32Ptr[ 0 ] = JL32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +//// BEQ +void recBEQ_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +void recBEQ_(int info) { recBEQ_process(info, 0); } +void recBEQ_consts(int info) { recBEQ_process(info, PROCESS_CONSTS); } +void recBEQ_constt(int info) { recBEQ_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQ, XMMINFO_READS|XMMINFO_READT); + +//// BNE +void recBNE_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + recSetBranchEQ(info, 1, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBNE_(int info) { recBNE_process(info, 0); } +void recBNE_consts(int info) { recBNE_process(info, PROCESS_CONSTS); } +void recBNE_constt(int info) { recBNE_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNE, XMMINFO_READS|XMMINFO_READT); + +//// BEQL +void recBEQL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBEQL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +void recBEQL_(int info) { recBEQL_process(info, 0); } +void recBEQL_consts(int info) { recBEQL_process(info, PROCESS_CONSTS); } +void recBEQL_constt(int info) { recBEQL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQL, XMMINFO_READS|XMMINFO_READT); + +//// BNEL +void recBNEL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm(branchTo); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBNEL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +void recBNEL_(int info) { recBNEL_process(info, 0); } +void recBNEL_consts(int info) { recBNEL_process(info, PROCESS_CONSTS); } +void recBNEL_constt(int info) { recBNEL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNEL, XMMINFO_READS|XMMINFO_READT); + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +//void recBLTZAL( void ) +//{ +// SysPrintf("BLTZAL\n"); +// _eeFlushAllUnused(); +// MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (int)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (int)BLTZAL ); +// branch = 2; +//} + +//////////////////////////////////////////////////// +void recBLTZAL(int info) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + SysPrintf("BLTZAL\n"); + _eeOnWriteReg(31, 0); + _eeFlushAllUnused(); + + _deleteEEreg(31, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[0], pc+4); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[1], 0); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + SysPrintf("BGEZAL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#endif + +//// BLEZ +void recBLEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//// BGTZ +void recBGTZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JL32( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JG32( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif \ No newline at end of file diff --git a/ix86-32/iR5900Branch.h b/ix86-32/iR5900Branch.h new file mode 100644 index 0000000000..3370b8a4cf --- /dev/null +++ b/ix86-32/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/ix86-32/iR5900Jump.c b/ix86-32/iR5900Jump.c new file mode 100644 index 0000000000..af4cf2b86b --- /dev/null +++ b/ix86-32/iR5900Jump.c @@ -0,0 +1,131 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + _deleteEEreg(31, 0); + GPR_SET_CONST(31); + g_cpuConstRegs[31].UL[0] = pc + 4; + g_cpuConstRegs[31].UL[1] = 0; + + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, _Rs_); + // uncomment when there are NO instructions that need to call interpreter +// int mmreg; +// if( GPR_IS_CONST1(_Rs_) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[_Rs_].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + + if ( _Rd_ ) + { + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + g_cpuConstRegs[_Rd_].UL[0] = pc + 4; + g_cpuConstRegs[_Rd_].UL[1] = 0; + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + + SetBranchReg(0xffffffff); +} + +#endif diff --git a/ix86-32/iR5900Jump.h b/ix86-32/iR5900Jump.h new file mode 100644 index 0000000000..d35f87c690 --- /dev/null +++ b/ix86-32/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/ix86-32/iR5900LoadStore.c b/ix86-32/iR5900LoadStore.c new file mode 100644 index 0000000000..abb22b2ccc --- /dev/null +++ b/ix86-32/iR5900LoadStore.c @@ -0,0 +1,4218 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +#else + +__declspec(align(16)) u64 retValues[2]; +extern u32 maxrecmem; +static u32 s_bCachingMem = 0; +static u32 s_nAddMemOffset = 0; +static u32 s_tempaddr = 0; + +void _eeOnLoadWrite(int reg) +{ + int regt; + + if( !reg ) return; + + _eeOnWriteReg(reg, 1); + regt = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + if( cpucaps.hasStreamingSIMD2Extensions && (reg != _Rs_) ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(regt, regt); + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + else SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } +} + +#ifdef WIN32_VIRTUAL_MEM + +extern void iMemRead32Check(); + +#define _Imm_co_ (*(s16*)PSM(pc)) + +// perf counters +#ifdef PCSX2_DEVBUILD +extern void StartPerfCounter(); +extern void StopPerfCounter(); +#else +#define StartPerfCounter() +#define StopPerfCounter() +#endif + +//////////////////////////////////////////////////// +//#define REC_SLOWREAD +//#define REC_SLOWWRITE +#define REC_FORCEMMX 0 + +// if sp, always mem write +int _eeIsMemWrite() { return _Rs_==29||_Rs_== 31||_Rs_==26||_Rs_==27; } // sp, ra, k0, k1 +// gp can be 1000a020 (jak1) + +void recTransferX86ToReg(int x86reg, int gprreg, int sign) +{ + //if( !REC_FORCEMMX ) assert( _checkMMXreg(MMX_GPR+gprreg, MODE_WRITE) == -1 ); + if( sign ) { + if( x86reg == EAX && EEINST_ISLIVE1(gprreg) ) CDQ(); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + + if(EEINST_ISLIVE1(gprreg)) { + if( x86reg == EAX ) MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], EDX ); + else { + SAR32ItoR(x86reg, 31); + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], x86reg ); + } + } + else { + EEINST_RESETHASLIVE1(gprreg); + } + } + else { + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + if(EEINST_ISLIVE1(gprreg)) MOV32ItoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(gprreg); + } +} + +#ifdef _DEBUG +void testaddrs() +{ + register int tempaddr; + + __asm mov tempaddr, ecx + //__asm mov incaddr, edx + + assert( (tempaddr < 0x40000000) || (tempaddr&0xd0000000)==0x50000000 || (tempaddr >= 0x80000000 && tempaddr < 0xc0000000) ); + //assert( (tempaddr>>28) == ((tempaddr+incaddr)>>28) ); + + __asm mov ecx, tempaddr +} +#endif + +#define SET_HWLOC() { \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[2]); \ + else x86SetJ8(j8Ptr[0]); \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[3]); \ + else x86SetJ8(j8Ptr[3]); \ + if (x86FpuState==MMX_STATE) { \ + if (cpucaps.has3DNOWInstructionExtensions) FEMMS(); \ + else EMMS(); \ + } \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ + if( s_bCachingMem & 4 ) AND32ItoR(ECX, 0x5fffffff); \ +} \ + +static u16 g_MemMasks0[16] = {0x00f0, 0x80f1, 0x00f2, 0x00f3, + 0x00f1, 0x00f5, 0x00f1, 0x00f5, + 0x00f5, 0x80f5, 0x00f5, 0x80f5, + 0x00f1, 0x00f1, 0x00f1, 0x00f5 }; +static u16 g_MemMasks8[16] = {0x0080, 0x8081, 0x0082, 0x0083, + 0x0081, 0x0085, 0x0081, 0x0085, + 0x0085, 0x8085, 0x0085, 0x8085, + 0x0081, 0x0081, 0x0081, 0x0085 }; +static u16 g_MemMasks16[16] ={0x0000, 0x8001, 0x0002, 0x0003, + 0x0001, 0x0005, 0x0001, 0x0005, + 0x0005, 0x8005, 0x0005, 0x8005, + 0x0001, 0x0001, 0x0001, 0x0005 }; + +void assertmem() +{ + __asm mov s_tempaddr, ecx + __asm mov s_bCachingMem, edx + SysPrintf("%x(%x) not mem write!\n", s_tempaddr, s_bCachingMem); + assert(0); +} + +int _eePrepareReg(int gprreg) +{ + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + + if( mmreg >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + mmreg |= MEM_XMMTAG; + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + if( mmxregs[mmreg].mode&MODE_WRITE ) mmreg |= MEM_MMXTAG; + else { + mmxregs[mmreg].needed = 0; // coX can possibly use all regs + mmreg = 0; + } + } + else { + mmreg = 0; + } + + return mmreg; +} + +int _eePrepareReg_coX(int gprreg, int num) +{ + int mmreg = _eePrepareReg(gprreg); + + if( (mmreg&MEM_MMXTAG) && num == 7 ) { + if( mmxregs[mmreg&0xf].mode & MODE_WRITE ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg], mmreg&0xf); + mmxregs[mmreg&0xf].mode &= ~MODE_WRITE; + mmxregs[mmreg&0xf].needed = 0; + } + } + + return mmreg; +} + +// returns true if should also include harware writes +int recSetMemLocation(int regs, int imm, int mmreg, int msize, int j32) +{ + s_bCachingMem = j32 ? 2 : 0; + s_nAddMemOffset = 0; + + //int num; + if( mmreg & MEM_XMMTAG ) { + SSE2_MOVD_XMM_to_R(ECX, mmreg&0xf); + } + else if( mmreg & MEM_MMXTAG ) { + MOVD32MMXtoR(ECX, mmreg&0xf); + SetMMXstate(); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ regs ].UL[ 0 ] ); + } + + if ( imm != 0 ) ADD32ItoR( ECX, imm ); + + LoadCW(); + +#ifdef _DEBUG + //CALLFunc((u32)testaddrs); +#endif + + + // 32bit version (faster?) +// MOV32RtoR(EAX, ECX); +// ROR32ItoR(ECX, 28); +// SHR32ItoR(EAX, 28); +// MOV32RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 2); +// AND8RtoR(ECX, EAX); +// ROR32ItoR(ECX, 4); +// // do extra alignment masks here +// OR32RtoR(EAX, EAX); + + if( _eeIsMemWrite() ) { + u8* ptr; + CMP32ItoR(ECX, 0x40000000); + ptr = JB8(0); + if( msize == 1 ) AND32ItoR(ECX, 0x5ffffff8); + else if( msize == 2 ) AND32ItoR(ECX, 0x5ffffff0); + else AND32ItoR(ECX, 0x5fffffff); + x86SetJ8(ptr); + if( msize == 1 ) AND8ItoR(ECX, 0xf8); + else if( msize == 2 ) AND8ItoR(ECX, 0xf0); +#ifdef _DEBUG + MOV32RtoR(EAX, ECX); + SHR32ItoR(EAX, 28); + CMP32ItoR(EAX, 1); + ptr = JNE8(0); + MOV32ItoR(EDX, _Rs_); + CALLFunc((u32)assertmem); + x86SetJ8(ptr); +#endif + return 0; + } + else { + // 16 bit version + MOV32RtoR(EAX, ECX); + ROR32ItoR(ECX, 28); + SHR32ItoR(EAX, 28); + MOV16RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 1); + AND8RtoR(ECX, EAX); + ROR32ItoR(ECX, 4); + + OR16RtoR(EAX, EAX); + + if( s_bCachingMem & 2 ) j32Ptr[2] = j32Ptr[3] = JS32(0); + else j8Ptr[0] = j8Ptr[3] = JS8(0); + } + + return 1; +} + + +void recLoad32(u32 bit, u32 imm, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _eeOnLoadWrite(_Rt_); + if( bit == 32 ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_MMXTAG; + else mmreg = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + mmreg = EAX; + } + + switch(bit) { + case 8: ineax = recMemConstRead8(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); break; + case 16: + assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 2 == 0 ); + ineax = recMemConstRead16(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); + break; + case 32: + // used by LWL/LWR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 4 == 0 ); + ineax = recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm); + break; + } + + if( ineax || !(mmreg&MEM_MMXTAG) ) { + if( mmreg&MEM_MMXTAG ) mmxregs[mmreg&0xf].inuse = 0; + recTransferX86ToReg(EAX, _Rt_, sign); + } + else { + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + + if( REC_FORCEMMX ) mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + else _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, imm, mmregs, 0, 0); + + if( mmreg >= 0 ) { + MOVD32RmOffsettoMMX(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset-(32-bit)/8); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + else { + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + if( mmreg >= 0 ) { + if( EEINST_ISLIVE1(_Rt_) ) MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_]); + else MOVD32RtoMMX(mmreg, EAX); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLoad32_co(u32 bit, u32 sign) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax = 0; + u32 written = 0; + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + + if( bit == 32 ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_MMXTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_MMXTAG; + else mmreg2 = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + mmreg1 = EBX; + mmreg2 = EAX; + } + + // do const processing + switch(bit) { + case 8: + if( recMemConstRead8(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead8(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 16: + if( recMemConstRead16(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead16(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 32: + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + break; + } + + if( !written && _Rt_ ) { + if( mmreg1&MEM_MMXTAG ) { + assert( mmxregs[mmreg1&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg1&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg1&0xf, 32-bit); + } + else recTransferX86ToReg(mmreg1, _Rt_, sign); + } + if( nextrt ) { + g_pCurInstInfo++; + if( !ineax && (mmreg2 & MEM_MMXTAG) ) { + assert( mmxregs[mmreg2&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg2&0xf, nextrt, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg2&0xf, 32-bit); + } + else { + if( mmreg2&MEM_MMXTAG ) mmxregs[mmreg2&0xf].inuse = 0; + recTransferX86ToReg(mmreg2, nextrt, sign); + } + g_pCurInstInfo--; + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + assert( !REC_FORCEMMX ); + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + switch(bit) { + case 8: + if( sign ) { + MOVSX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 16: + if( sign ) { + MOVSX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 32: + MOV32RmtoROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EBX, _Rt_, sign); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + break; + case 16: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + break; + case 32: + MOV32RtoM((u32)&s_tempaddr, ECX); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( nextrt ) { + g_pCurInstInfo++; + recTransferX86ToReg(EAX, nextrt, sign); + g_pCurInstInfo--; + } + } +} + +void recLB( void ) { recLoad32(8, _Imm_, 1); } +void recLB_co( void ) { recLoad32_co(8, 1); } +void recLBU( void ) { recLoad32(8, _Imm_, 0); } +void recLBU_co( void ) { recLoad32_co(8, 0); } +void recLH( void ) { recLoad32(16, _Imm_, 1); } +void recLH_co( void ) { recLoad32_co(16, 1); } +void recLHU( void ) { recLoad32(16, _Imm_, 0); } +void recLHU_co( void ) { recLoad32_co(16, 0); } +void recLW( void ) { recLoad32(32, _Imm_, 1); } +void recLW_co( void ) { recLoad32_co(32, 1); } +void recLWU( void ) { recLoad32(32, _Imm_, 0); } +void recLWU_co( void ) { recLoad32_co(32, 0); } + +//////////////////////////////////////////////////// + +// paired with LWR +void recLWL_co(void) { recLoad32(32, _Imm_-3, 1); } + +void recLWL( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, 24-shift*8); + AND32ItoR(ECX, (0xffffff>>(shift*8))); + OR32RtoR(EAX, ECX); + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) { + // mem << LWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHL32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff); + SAR32CLtoR(EDX); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(EDX, ECX); + + // combine + OR32RtoR(EAX, EDX); + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// + +// paired with LWL +void recLWR_co(void) { recLoad32(32, _Imm_, 1); } + +void recLWR( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, shift*8); + AND32ItoR(ECX, (0xffffff00<<(24-shift*8))); + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + PUSH32R(ECX); + AND32ItoR(ECX, ~3); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) + { + // mem << LWL_SHIFT[shift] + MOV32RtoR(ECX, EDX); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 3); // *8 + SHR32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(EDX, ECX); + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(ECX, EDX); + + // combine + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// +void recLoad64(u32 imm, int align) +{ + int mmreg; + int mask = align ? ~7 : ~0; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // also used by LDL/LDR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 8 == 0 ); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg); + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + if( !_hasFreeMMXreg() && _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ|MODE_WRITE); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, t0reg); + + if( _Rt_ ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UD[0], t0reg); + } + + _freeMMXreg(t0reg); + } + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + MOVQRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + + SetMMXstate(); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + SSE_MOVLPSRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + SSE_MOVLPS_M64_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + } + else { + int t0reg = _Rt_ ? _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE) : -1; + + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + if( t0reg >= 0 ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + SetMMXstate(); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( _Rt_ ) { + //_deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + ADD32ItoR(ESP, 4); + + if( t0reg >= 0 ) MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); +} + +void recLD(void) { recLoad64(_Imm_, 1); } + +void recLD_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLD(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int mmreg1 = -1, mmreg2 = -1, t0reg = -1, t1reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + if( nextrt ) _eeOnWriteReg(nextrt, 0); + + if( _Rt_ ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 < 0 ) { + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg1 >= 0 ) mmreg1 |= 0x8000; + } + + if( mmreg1 < 0 && _hasFreeMMXreg() ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + if( nextrt ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 < 0 ) { + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE|MODE_READ); + if( mmreg2 >= 0 ) mmreg2 |= 0x8000; + } + + if( mmreg2 < 0 && _hasFreeMMXreg() ) mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_WRITE); + } + + if( mmreg1 < 0 || mmreg2 < 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( mmreg1 < 0 && mmreg2 < 0 && _hasFreeMMXreg() ) { + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + else t1reg = t0reg; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 1, 0); + + if( mmreg1 >= 0 ) { + if( mmreg1 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _Rt_ ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], t0reg); + } + } + + if( mmreg2 >= 0 ) { + if( mmreg2 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + else MOVQRmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( nextrt ) { + MOVQRmtoROffset(t1reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ], t1reg); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg1 >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg1 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg1, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + if( _Rt_ ) { + _deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + + if( mmreg2 >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + + if( mmreg2 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + else MOVQMtoR(mmreg2, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + } + else { + if( nextrt ) { + _deleteEEreg(nextrt, 0); + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + } + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + if( mmreg1 < 0 || mmreg2 < 0 || !(mmreg1&0x8000) || !(mmreg2&0x8000) ) SetMMXstate(); + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + if( t0reg != t1reg && t1reg >= 0 ) _freeMMXreg(t1reg); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +void recLD_coX( int num ) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLD(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _eeOnWriteReg(nextrts[i], 0); + } + + if( _Rt_ ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg < 0 ) { + mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + } + else mmreg |= MEM_MMXTAG; + } + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckGPRtoMMX(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + if( mmregs[i] < 0 ) { + mmregs[i] = _allocCheckGPRtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE|MODE_READ); + if( mmregs[i] >= 0 ) mmregs[i] |= MEM_XMMTAG; + else mmregs[i] = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_WRITE)|MEM_MMXTAG; + } + else mmregs[i] |= MEM_MMXTAG; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 1, 0); + + if( mmreg >= 0 ) { + if( mmreg & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + u32 off = PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_; + + if( mmregs[i] >= 0 ) { + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmregs[i]&0xf, ECX, off); + else MOVQRmtoROffset(mmregs[i]&0xf, ECX, off); + } + } + + if( dohw ) { + if( (s_bCachingMem & 2) || num > 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead64 ); + } + + for(i = 0; i < num; ++i ) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( mmregs[i] >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + CALLFunc( (int)recMemRead64 ); + + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + else MOVQMtoR(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + } + else { + MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead64 ); + } + } + + ADD32ItoR(ESP, 4); + + if( (s_bCachingMem & 2) || num > 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +//////////////////////////////////////////////////// +void recLDL_co(void) { + recLoad64(_Imm_-7, 0); } + +void recLDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR_co(void) { recLoad64(_Imm_, 0); } + +void recLDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + int mmreg = -1; +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Rt_ ) { + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_XMM) || !(g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + else { + int t0reg; + _deleteGPRtoXMMreg(_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + mmreg |= t0reg<<4; + } + } + else mmreg = _allocTempXMMreg(XMMT_INT, -1); + + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + if( !_Rt_ ) _freeXMMreg(mmreg); + if( IS_MMXREG(mmreg) ) { + // flush temp + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], (mmreg>>4)&0xf); + _freeMMXreg((mmreg>>4)&0xf); + } + else assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int t0reg = -1; + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + // check if can process mmx + if( _hasFreeMMXreg() ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) { + mmreg |= MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg < 0 ) + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg & MEM_MMXTAG ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else { + SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg & MEM_MMXTAG ) MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + ADD32ItoR(ESP, 4); + } + } + else { + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQ_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLQ(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int t0reg = -1; + int mmregs = _eePrepareReg(_Rs_); + + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + if( _hasFreeMMXreg() ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) { + mmreg1 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg1 < 0 ) { + mmreg1 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + } + + if( nextrt ) { + _eeOnWriteReg(nextrt, 0); + + if( _hasFreeMMXreg() ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) { + mmreg2 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+nextrt, 2); + + if( mmreg2 < 0 ) { + mmreg2 = _allocGPRtoXMMreg(-1, nextrt, MODE_WRITE); + } + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg1 & MEM_MMXTAG ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else { + SSEX_MOVDQARmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + } + + if( nextrt ) { + if( mmreg2 & MEM_MMXTAG ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOVQRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((u32)&cpuRegs.GPR.r[nextrt].UL[2], t0reg); + } + else { + SSEX_MOVDQARmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrt].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead128 ); + + if( _Rt_) { + if( mmreg1 & MEM_MMXTAG ) MOVQMtoR(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + if( nextrt ) { + if( mmreg2 & MEM_MMXTAG ) MOVQMtoR(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ]); + else SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ] ); + } + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } +} + +// coissues more than 2 LQs +void recLQ_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLQ(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + if( _Rt_ ) _deleteMMXreg(MMX_GPR+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + if( nextrts[i] ) _deleteMMXreg(MMX_GPR+nextrts[i], 2); + } + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + for(i = 0; i < num; ++i) { + if( nextrts[i] ) { + _eeOnWriteReg(nextrts[i], 0); + mmregs[i] = _allocGPRtoXMMreg(-1, nextrts[i], MODE_WRITE); + } + else mmregs[i] = -1; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 2, 1); + + if( _Rt_ ) SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + if( nextrts[i] ) SSEX_MOVDQARmtoROffset(mmregs[i], ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + if( _Rt_) SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( nextrts[i] ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead128 ); + if( nextrts[i] ) SSEX_MOVDQA_M128_to_XMM(mmregs[i], (int)&cpuRegs.GPR.r[ nextrts[i] ].UL[ 0 ] ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +extern void recClear64(BASEBLOCK* p); +extern void recClear128(BASEBLOCK* p); + +// check if clearing executable code, size is in dwords +void recMemConstClear(u32 mem, u32 size) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !recLUT[mem>>16] ) + return; + + //iFlushCall(0); // just in case + + // check if mem is executable, and clear it + //CMP32ItoM((u32)&maxrecmem, mem); + //j8Ptr[5] = JBE8(0); + + // can clear now + if( size == 1 ) { + CMP32ItoM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); + } + else if( size == 2 ) { + // need to clear 8 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+8, 0); + j8Ptr[7] = JNE8(0); + + j8Ptr[8] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[6] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear64); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[8] ); + } + else { + assert( size == 4 ); + // need to clear 16 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK), 0); + j8Ptr[7] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*2, 0); + j8Ptr[8] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*3, 0); + j8Ptr[9] = JNE8(0); + + j8Ptr[10] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[8] ); + x86SetJ8( j8Ptr[9] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear128); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[10] ); + } + + //x86SetJ8(j8Ptr[5]); +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear32() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, recLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call recClearMem + add esp, 4 +ClearRet: + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear64() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear64 + ret +Clear64: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check both blocks + cmp dword ptr [edx], 0 + jne DoClear0 + cmp dword ptr [edx+8], 0 + jne DoClear1 + ret + +DoClear1: + add edx, 8 +DoClear0: + sub esp, 4 + mov dword ptr [esp], edx + call recClear64 + add esp, 4 + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear128() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear128 + ret +Clear128: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check all 4 blocks + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + ret + +DoClear: + sub esp, 4 + mov dword ptr [esp], edx + call recClear128 + add esp, 4 + ret + } +} + +void recStore_raw(EEINST* pinst, int bit, int x86reg, int gprreg, u32 offset) +{ + if( bit == 128 ) { + int mmreg; + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + + SetMMXstate(); + } + else { + + if( GPR_IS_CONST1( gprreg ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + SetMMXstate(); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( _hasFreeMMXreg() ) { + int t0reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); +// MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); +// MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset+8); + } + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + } + return; + } + + if( GPR_IS_CONST1( gprreg ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 16: MOV16ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 32: MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 64: + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + break; + } + } + else { + int mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ); + if( mmreg < 0 ) { + mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + if( mmreg >= 0 ) mmreg |= 0x8000; + } + + if( bit == 64 ) { + //sd + if( mmreg >= 0 ) { + if( mmreg & 0x8000 ) { + SSE_MOVLPSRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVQRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + if( (mmreg = _allocCheckGPRtoMMX(pinst, gprreg, MODE_READ)) >= 0 ) { + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_GPR+gprreg, MODE_READ); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + } + } + } + else if( bit == 32 ) { + // sw + if( mmreg >= 0 ) { + if( mmreg & 0x8000) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVD32MMXtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); + } + } + else { + // sb, sh + if( mmreg >= 0) { + if( mmreg & 0x8000) { + if( !(xmmregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + else { + if( !(mmxregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + } + + if( mmreg >= 0) { + if( mmreg & 0x8000 ) SSE2_MOVD_XMM_to_R(x86reg, mmreg&0xf); + else { + MOVD32MMXtoR(x86reg, mmreg&0xf); + SetMMXstate(); + } + } + else { + switch(bit) { + case 8: MOV8MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + + switch(bit) { + case 8: MOV8RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 16: MOV16RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 32: MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + } + } + } +} + +void recStore_call(int bit, int gprreg, u32 offset) +{ + // some type of hardware write + if( GPR_IS_CONST1( gprreg ) ) { + if( bit == 128 ) { + if( gprreg > 0 ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], g_cpuConstRegs[gprreg].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], g_cpuConstRegs[gprreg].UL[1]); + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + if( !(g_cpuFlushedConstReg&(1<= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + // sd + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVLPS_XMM_to_M64((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + SetMMXstate(); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else { + // sb, sh, sw + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + SSE2_MOVD_XMM_to_R(EAX, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE)) { + MOVD32MMXtoR(EAX, mmreg); + SetMMXstate(); + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + } + } + + if( offset != 0 ) ADD32ItoR(ECX, offset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)recMemWrite8 ); break; + case 16: CALLFunc( (int)recMemWrite16 ); break; + case 32: CALLFunc( (int)recMemWrite32 ); break; + case 64: CALLFunc( (int)recMemWrite64 ); break; + case 128: CALLFunc( (int)recMemWrite128 ); break; + } +} + +int _eePrepConstWrite128(int gprreg) +{ + int mmreg = 0; + + if( GPR_IS_CONST1(gprreg) ) { + if( gprreg ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + _freeMMXreg(mmreg); + mmreg |= (gprreg<<16)|MEM_EECONSTTAG; + } + else { + mmreg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(mmreg, mmreg); + _freeXMMreg(mmreg); + mmreg |= MEM_XMMTAG; + } + } + else { + if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + int mmregtemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmregtemp, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + mmreg |= (mmregtemp<<4)|MEM_MMXTAG; + _freeMMXreg(mmregtemp); + } + else mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ)|MEM_XMMTAG; + } + + return mmreg; +} + +void recStore(int bit, u32 imm, int align) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+imm; + int doclear = 0; + StopPerfCounter(); + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite8(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 16: + assert( (addr)%2 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite16(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 32: + // used by SWL/SWR + //assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + break; + case 64: + { + //assert( (addr)%8 == 0 ); + int mask = align ? ~7 : ~0; + + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite64(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else { + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + + if( doclear ) { + recMemConstClear((addr)&~7, 2); + } + + break; + } + case 128: + assert( (addr)%16 == 0 ); + + if( recMemConstWrite128((addr)&~15, _eePrepConstWrite128(_Rt_)) ) { + CMP32ItoM((u32)&maxrecmem, addr); + j8Ptr[0] = JB8(0); + recMemConstClear((addr)&~15, 4); + x86SetJ8(j8Ptr[0]); + } + + break; + } + + StartPerfCounter(); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, imm, mmregs, align ? bit/64 : 0, 0); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[4] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + if( bit < 32 || !align ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[5] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + StopPerfCounter(); + recStore_call(bit, _Rt_, s_nAddMemOffset); + StartPerfCounter(); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recStore_co(int bit, int align) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_; + u32 coaddr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_; + int mmreg, t0reg = -1, mmreg2; + int doclear = 0; + + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite8(addr, EAX); + } + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite8(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite8(coaddr, EAX); + } + break; + case 16: + assert( (addr)%2 == 0 ); + assert( (coaddr)%2 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite16(addr, EAX); + } + + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite16(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite16(coaddr, EAX); + } + break; + case 32: + assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite32(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_XMMTAG|(nextrt<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_MMXTAG|(nextrt<<16)); + } + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite32(coaddr, EAX); + } + + break; + case 64: + { + int mask = align ? ~7 : ~0; + //assert( (addr)%8 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + + if( GPR_IS_CONST1(nextrt) ) mmreg2 = MEM_EECONSTTAG|(nextrt<<16); + else if( (mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + mmreg2 |= MEM_XMMTAG|(nextrt<<16); + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_READ)|MEM_MMXTAG|(nextrt<<16); + + doclear = recMemConstWrite64((addr)&mask, mmreg); + doclear |= recMemConstWrite64((coaddr)&mask, mmreg2); + doclear <<= 1; + break; + } + case 128: + assert( (addr)%16 == 0 ); + + mmreg = _eePrepConstWrite128(_Rt_); + mmreg2 = _eePrepConstWrite128(nextrt); + doclear = recMemConstWrite128((addr)&~15, mmreg); + doclear |= recMemConstWrite128((coaddr)&~15, mmreg2); + doclear <<= 2; + break; + } + + if( doclear ) { + u8* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+(_Imm_ < _Imm_co_ ? _Imm_ : _Imm_co_)); + ptr = JB8(0); + recMemConstClear((addr)&~(doclear*4-1), doclear); + recMemConstClear((coaddr)&~(doclear*4-1), doclear); + x86SetJ8A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int off = _Imm_co_-_Imm_; + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align ? bit/64 : 0, bit==128); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + recStore_raw(g_pCurInstInfo+1, bit, EBX, nextrt, s_nAddMemOffset+off); + + // clear the writes, do only one camera (with the lowest addr) + if( off < 0 ) ADD32ItoR(ECX, s_nAddMemOffset+off); + else if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( off < 0 ) ADD32ItoR(ECX, -off); + else ADD32ItoR(ECX, off); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(bit, _Rt_, s_nAddMemOffset); + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(bit, nextrt, s_nAddMemOffset+_Imm_co_-_Imm_); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recSB( void ) { recStore(8, _Imm_, 1); } +void recSB_co( void ) { recStore_co(8, 1); } +void recSH( void ) { recStore(16, _Imm_, 1); } +void recSH_co( void ) { recStore_co(16, 1); } +void recSW( void ) { recStore(32, _Imm_, 1); } +void recSW_co( void ) { recStore_co(32, 1); } + +//////////////////////////////////////////////////// +void recSWL_co(void) { recStore(32, _Imm_-3, 0); } + +void recSWL( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0xffffff00<<(shift*8)); + SHR32ItoR(ECX, 24-shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem >> SWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHR32CLtoR(EBX); + + // mov temp and compute _rt_ & SWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +//////////////////////////////////////////////////// +void recSWR_co(void) { recStore(32, _Imm_, 0); } + +void recSWR( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0x00ffffff>>(24-shift*8)); + SHL32ItoR(ECX, shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem << SWR_SHIFT[shift] + MOV32RtoR(ECX, EDX); + SHL32CLtoR(EBX); + + // mov temp and compute _rt_ & SWR_MASK[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0x00ffffff); + SHR32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +void recSD( void ) { recStore(64, _Imm_, 1); } +void recSD_co( void ) { recStore_co(64, 1); } + +// coissues more than 2 SDs +void recSD_coX(int num, int align) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + u32 mask = align ? ~7 : ~0; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&mask, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + if( GPR_IS_CONST1(nextrts[i]) ) mmreg = MEM_EECONSTTAG|(nextrts[i]<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrts[i], MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_READ)|MEM_MMXTAG|(nextrts[i]<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&mask, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~7, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~7, 2); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align, 1); + + recStore_raw(g_pCurInstInfo, 64, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 64, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear64); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear64); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(64, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(64, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +//////////////////////////////////////////////////// +void recSDL_co(void) { recStore(64, _Imm_-7, 0); } + +void recSDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR_co(void) { recStore(64, _Imm_, 0); } + +void recSDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { recStore(128, _Imm_, 1); } +void recSQ_co( void ) { recStore_co(128, 1); } + +// coissues more than 2 SQs +void recSQ_coX(int num) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + mmreg = _eePrepConstWrite128(_Rt_); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + mmreg = _eePrepConstWrite128(nextrts[i]); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+imm)&~15, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~15, 4); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 1); + + recStore_raw(g_pCurInstInfo, 128, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 128, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear128); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear128); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(128, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(128, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + mmreg = EAX; + } + + if( !(mmreg&MEM_XMMTAG) ) + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + else +#endif + { + int dohw; + int regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + + if( regt ) SSE2_MOVD_R_to_XMM(regt, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 written = 0; + int ineax, mmreg1, mmreg2; + + mmreg1 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_XMMTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_XMMTAG; + else mmreg2 = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_XMMTAG ) xmmregs[mmreg1&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + + if( !written ) { + if( !(mmreg1&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + } + + if( ineax || !(mmreg2 & MEM_XMMTAG) ) { + if( mmreg2&MEM_XMMTAG ) xmmregs[mmreg2&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int regt, regtnext; + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + regtnext = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( regtnext >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regtnext, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32R(ECX); + CALLFunc( (int)recMemRead32 ); + POP32R(ECX); + + if( regt >= 0 ) { + SSE2_MOVD_R_to_XMM(regt, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( regtnext >= 0 ) { + SSE2_MOVD_R_to_XMM(regtnext, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recLWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax; + u32 written = 0; + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + // recompile two at a time + for(i = 0; i < num-1; i += 2) { + nextrts[0] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + nextrts[1] = ((*(u32*)(PSM(pc+i*4+4)) >> 16) & 0x1F); + + written = 0; + mmregs[0] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[0], MODE_WRITE); + if( mmregs[0] >= 0 ) mmregs[0] |= MEM_XMMTAG; + else mmregs[0] = EBX; + + mmregs[1] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+2, nextrts[1], MODE_WRITE); + if( mmregs[1] >= 0 ) mmregs[1] |= MEM_XMMTAG; + else mmregs[1] = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmregs[0], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmregs[0]&MEM_XMMTAG ) xmmregs[mmregs[0]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmregs[1], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4+4))); + + if( !written ) { + if( !(mmregs[0]&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + } + + if( ineax || !(mmregs[1] & MEM_XMMTAG) ) { + if( mmregs[1]&MEM_XMMTAG ) xmmregs[mmregs[1]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[1] ].UL, EAX ); + } + } + + if( i < num ) { + // one left + int nextrt = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrt, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _deleteMMXreg(MMX_FPU+nextrts[i], 2); + } + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmregs[i], ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead32 ); + + if( mmreg >= 0 ) SSE2_MOVD_R_to_XMM(mmreg, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( mmregs[i] >= 0 ) SSE2_MOVD_R_to_XMM(mmregs[i], EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recSWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrt<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + int mmreg1, mmreg2; + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + assert( _checkMMXreg(MMX_FPU+nextrt, MODE_READ) == -1 ); + + mmreg1 = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if(mmreg1 >= 0 ) { + if( mmreg2 >= 0 ) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + else { + if( mmreg2 >= 0 ) { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32MtoR(EDX, (int)&fpuRegs.fpr[ nextrt ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg1 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg1); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + if( mmreg2 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg2); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recSWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + for(i = 0; i < num; ++i) { + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)), mmreg); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + for(i = 0; i < num; ++i) { + assert( _checkMMXreg(MMX_FPU+nextrts[i], MODE_READ) == -1 ); + mmregs[i] = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmregs[i], PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + if( mmregs[i] >= 0 && (xmmregs[mmregs[i]].mode&MODE_WRITE) ) SSE2_MOVD_XMM_to_R(EAX, mmregs[i]); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + CALLFunc( (int)recMemWrite32 ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else mmreg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + if( !_Ft_ ) _freeXMMreg(mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Ft_ ) { + s8* rawreadptr = x86Ptr; + + SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + CALLFunc( (int)recMemRead128 ); + SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0] ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + else { + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQC2_co( void ) +{ + int mmreg1 = -1, mmreg2 = -1, t0reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg1 >= 0 ? mmreg1 : t0reg); + + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + else if( t0reg < 0 ) t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg2 >= 0 ? mmreg2 : t0reg); + + if( t0reg >= 0 ) _freeXMMreg(t0reg); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + if( mmreg1 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + if( mmreg2 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Ft_ ) PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg1 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0] ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&VU0.VF[nextrt].UD[0], 0 ); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg2 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0] ); + + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[1]); + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg); + } + } + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +void recSQC2_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1, mmreg2; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg1); + recMemConstWrite128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg2); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg1 = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_VFREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( mmreg1 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg1 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg1); + } + else if( _hasFreeMMXreg() ) { + mmreg1 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg1); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( mmreg2 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( _hasFreeXMMreg() ) { + mmreg2 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + _freeXMMreg(mmreg2); + } + else if( _hasFreeMMXreg() ) { + mmreg2 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UL[2]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + SetMMXstate(); + _freeMMXreg(mmreg2); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+4); + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( mmreg1 >= 0) { + if( xmmregs[mmreg1].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg1); + } + } + + MOV32RtoM((u32)&s_tempaddr, ECX); + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + if( mmreg2 >= 0) { + if( xmmregs[mmreg2].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[nextrt].UD[0], mmreg2); + } + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + MOV32ItoR(EAX, (int)&VU0.VF[nextrt].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +#else + +__declspec(align(16)) u32 dummyValue[4]; + +//////////////////////////////////////////////////// +void recLB( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVSX32R8toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLBU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R8toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLH( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOVSX32R16toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLHU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R16toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLW( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWR ); +} + +//////////////////////////////////////////////////// +extern void MOV64RmtoR( x86IntRegType to, x86IntRegType from ); + +void recLD( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead64 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + AND32ItoR( EAX, ~0xf ); + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); + +} + +//////////////////////////////////////////////////// +void recSB( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite8 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite16 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite64 ); + ADD32ItoR( ESP, 12 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + AND32ItoR( EAX, ~0xf ); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +#endif + +#endif \ No newline at end of file diff --git a/ix86-32/iR5900LoadStore.h b/ix86-32/iR5900LoadStore.h new file mode 100644 index 0000000000..fd078b9cf9 --- /dev/null +++ b/ix86-32/iR5900LoadStore.h @@ -0,0 +1,90 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSDL( void ); +void recSDR( void ); +void recSQ( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +// coissues +#ifdef WIN32_VIRTUAL_MEM +void recLB_co( void ); +void recLBU_co( void ); +void recLH_co( void ); +void recLHU_co( void ); +void recLW_co( void ); +void recLWU_co( void ); +void recLWL_co( void ); +void recLWR_co( void ); +void recLD_co( void ); +void recLDR_co( void ); +void recLDL_co( void ); +void recLQ_co( void ); +void recSB_co( void ); +void recSH_co( void ); +void recSW_co( void ); +void recSWL_co( void ); +void recSWR_co( void ); +void recSD_co( void ); +void recSDL_co( void ); +void recSDR_co( void ); +void recSQ_co( void ); +void recLWC1_co( void ); +void recSWC1_co( void ); +void recLQC2_co( void ); +void recSQC2_co( void ); + +// coissue-X +void recLD_coX(int num); +void recLQ_coX(int num); +void recLWC1_coX(int num); +void recSD_coX(int num); +void recSQ_coX(int num); +void recSWC1_coX(int num); + +#endif + +#endif diff --git a/ix86-32/iR5900Move.c b/ix86-32/iR5900Move.c new file mode 100644 index 0000000000..0c84c53595 --- /dev/null +++ b/ix86-32/iR5900Move.c @@ -0,0 +1,822 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#elif defined(EE_CONST_PROP) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//// LUI +void recLUI(int info) +{ + int mmreg; + if(!_Rt_) return; + + _eeOnWriteReg(_Rt_, 1); + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE)) >= 0 ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + } + + _deleteEEreg(_Rt_, 0); + GPR_SET_CONST(_Rt_); + g_cpuConstRegs[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +//////////////////////////////////////////////////// +void recMFHILO(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + assert( regd != reghi ); + + xmmregs[regd].inuse = 0; + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + else { + SSE_MOVLPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + SSE2_MOVQ_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + reghi = _checkMMXreg(MMX_GPR+xmmhilo, MODE_READ); + + if( reghi >= 0 ) { + + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], regd); + } + xmmregs[regd].inuse = 0; + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + SetMMXstate(); + + if( regd >= 0 ) { + MOVQRtoR(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + else SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 0 ] : (int)&cpuRegs.LO.UL[ 0 ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 1 ] : (int)&cpuRegs.LO.UL[ 1 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } +} + +void recMTHILO(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + assert( reghi != regs ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + _deleteGPRtoXMMreg(_Rs_, 0); + SSE2_PUNPCKHQDQ_XMM_to_XMM(reghi, reghi); + SSE2_PUNPCKLQDQ_XMM_to_XMM(regs, reghi); + + // swap regs + xmmregs[regs] = xmmregs[reghi]; + xmmregs[reghi].inuse = 0; + xmmregs[regs].mode |= MODE_WRITE; + } + else { + SSE2EMU_MOVSD_XMM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + if( EEINST_ISLIVE2(xmmhilo) ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64(addrhilo+8, reghi); + } + xmmregs[reghi].inuse = 0; + MOVQRtoM(addrhilo, regs); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + _flushConstReg(_Rs_); + SSE_MOVLPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + } + else { + reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, xmmhilo, MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + //SetMMXstate(); + SSE2_MOVDQ2Q_XMM_to_MM(reghi, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoR(reghi, regs); + } + else { + _flushConstReg(_Rs_); + MOVQMtoR(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + } + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+4, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo, EAX ); + MOV32RtoM( addrhilo+4, EDX ); + } + } + } + } + } +} + +void recMFHI( void ) +{ + recMFHILO(1); +} + +void recMFLO( void ) +{ + recMFHILO(0); +} + +void recMTHI( void ) +{ + recMTHILO(1); +} + +void recMTLO( void ) +{ + recMTHILO(0); +} + +//////////////////////////////////////////////////// +void recMFHILO1(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + SSEX_MOVHLPS_XMM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + _deleteEEreg(_Rd_, 0); + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PUNPCKHQDQ_M128_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + SSE2_PSHUFD_XMM_to_XMM(regd, regd, 0x4e); + } + else { + SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + } + else { + SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + + xmmregs[regd].mode |= MODE_WRITE; + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 2 ] : (int)&cpuRegs.LO.UL[ 2 ]); + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 3 ] : (int)&cpuRegs.LO.UL[ 3 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + } + } +} + +void recMTHILO1(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, xmmhilo, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_XMM_to_XMM(reghi, regs); + else SSE_MOVLHPS_XMM_to_XMM(reghi, regs); + } + else { + _deleteEEreg(_Rs_, 1); + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_M128_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + else SSE_MOVHPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ]); + + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo+8, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo+8, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo+8, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+12, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo+8, EAX ); + MOV32RtoM( addrhilo+12, EDX ); + } + } + } + } +} + +void recMFHI1( void ) +{ + recMFHILO1(1); +} + +void recMFLO1( void ) +{ + recMFHILO1(0); +} + +void recMTHI1( void ) +{ + recMTHILO1(1); +} + +void recMTLO1( void ) +{ + recMTHILO1(0); +} + +//// MOVZ +void recMOVZtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +__declspec(align(16)) static s_zero[4] = {0,0,0xffffffff, 0xffffffff}; + +void recMOVZtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVZtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + if( info & PROCESS_EE_MMX ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + return; + } + + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVZtemp_(int info) +{ + int t0reg = -1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVZtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVZ() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + } + + recMOVZtemp(); +} + +//// MOVN +void recMOVNtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +void recMOVNtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVNtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVNtemp_(int info) +{ + int t0reg=-1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVNtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVN() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + } + + recMOVNtemp(); +} + +#else + +//////////////////////////////////////////////////// +void recLUI( void ) +{ + if(!_Rt_) return; + if ( _Imm_ < 0 ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0xffffffff ); //V + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); //V + } +} + +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +#endif diff --git a/ix86-32/iR5900Move.h b/ix86-32/iR5900Move.h new file mode 100644 index 0000000000..ae501e334e --- /dev/null +++ b/ix86-32/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/ix86-32/iR5900MultDiv.c b/ix86-32/iR5900MultDiv.c new file mode 100644 index 0000000000..28c720a62e --- /dev/null +++ b/ix86-32/iR5900MultDiv.c @@ -0,0 +1,949 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC( MULT1 ); +REC_FUNC( MULTU1 ); + +REC_FUNC(DIV); +REC_FUNC(DIVU); +REC_FUNC( DIV1 ); +REC_FUNC( DIVU1 ); + +REC_FUNC( MADD ); +REC_FUNC( MADDU ); +REC_FUNC( MADD1 ); +REC_FUNC( MADDU1 ); + +#elif defined(EE_CONST_PROP) + +// if upper is 1, write in upper 64 bits of LO/HI +void recWritebackHILO(int info, int writed, int upper) +{ + int regd, reglo = -1, reghi, savedlo = 0; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + MOV32RtoR( ECX, EDX ); + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + + _deleteMMXreg(XMMGPR_LO, 2); + + if( (reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ)) >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + + xmmregs[reglo].inuse = 0; + reglo = -1; + } + + CDQ(); + MOV32RtoM( loaddr, EAX ); + MOV32RtoM( loaddr+4, EDX ); + savedlo = 1; + } + + if ( writed && _Rd_ ) + { + _eeOnWriteReg(_Rd_, 1); + + regd = -1; + if( g_pCurInstInfo->regs[_Rd_] & EEINST_MMX ) { + + if( savedlo ) { + regd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + MOVQMtoR(regd, loaddr); + } + } + else if( g_pCurInstInfo->regs[_Rd_] & EEINST_XMM ) { + if( savedlo ) { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE|MODE_READ); + if( regd >= 0 ) { + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + regd |= 0x8000; + } + } + } + + if( regd < 0 ) { + _deleteEEreg(_Rd_, 0); + + if( EEINST_ISLIVE1(_Rd_) && !savedlo ) CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else EEINST_RESETHASLIVE1(_Rd_); + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + _deleteMMXreg(XMMGPR_HI, 2); + + if( (reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ)) >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + else SSE_MOVHPS_XMM_to_M64(hiaddr+8, reghi); + } + + xmmregs[reghi].inuse = 0; + reghi = -1; + } + + MOV32RtoM(hiaddr, ECX ); + SAR32ItoR(ECX, 31); + MOV32RtoM(hiaddr+4, ECX ); + } +} + +void recWritebackHILOMMX(int info, int regsource, int writed, int upper) +{ + int regd, t0reg, t1reg = -1; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + SetMMXstate(); + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, regsource); + PSRADItoR(t0reg, 31); // shift in 0s + + if( (g_pCurInstInfo->regs[XMMGPR_LO] & testlive) || (writed && _Rd_) ) { + if( (g_pCurInstInfo->regs[XMMGPR_HI] & testlive) ) + { + if( !_hasFreeMMXreg() ) { + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t1reg, regsource); + } + + PUNPCKLDQRtoR(regsource, t0reg); + } + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + int reglo; + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + MOVQRtoR(reglo, regsource); + } + else { + reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ); + + MOVQRtoM(loaddr, regsource); + + if( reglo >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + xmmregs[reglo].inuse = 0; + reglo = -1; + } + } + } + + if ( writed && _Rd_ ) + { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + if( regd != regsource ) MOVQRtoR(regd, regsource); + } + else { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ); + + if( regd >= 0 ) { + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + // lo written + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + + xmmregs[regd].inuse = 0; + } + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + int mmreg = -1, reghi; + + if( t1reg >= 0 ) { + PUNPCKHDQRtoR(t1reg, t0reg); + mmreg = t1reg; + } + else { + // can't modify regsource + PUNPCKHDQRtoR(t0reg, regsource); + mmreg = t0reg; + PSHUFWRtoR(t0reg, t0reg, 0x4e); + } + + if( upper ) { + reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ); + if( reghi >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + } + + xmmregs[reghi].inuse = 0; + MOVQRtoM(hiaddr, mmreg); + } + else { + _deleteGPRtoXMMreg(XMMGPR_HI, 2); + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + mmxregs[mmreg].mode = MODE_WRITE; + mmxregs[mmreg].reg = MMX_GPR+MMX_HI; + + if( t1reg >= 0 ) t1reg = -1; + else t0reg = -1; + } + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg&0xf); + if( t1reg >= 0 ) _freeMMXreg(t1reg&0xf); +} + +void recWritebackConstHILO(u64 res, int writed, int upper) +{ + int reglo, reghi; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + MOVQMtoR(reglo, (u32)ptr); + } + else { + reglo = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE|MODE_READ); + + if( reglo >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reglo, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reglo, (u32)ptr); + } + else { + MOV32ItoM(loaddr, res & 0xffffffff); + MOV32ItoM(loaddr+4, (res&0x80000000)?0xffffffff:0); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + if( !upper && (reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + MOVQMtoR(reghi, (u32)ptr); + } + else { + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reghi, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reghi, (u32)ptr); + } + else { + _deleteEEreg(XMMGPR_HI, 0); + MOV32ItoM(hiaddr, res >> 32); + MOV32ItoM(hiaddr+4, (res>>63)?0xffffffff:0); + } + } + } + + if (!writed || !_Rd_) return; + g_cpuConstRegs[_Rd_].UD[0] = (s32)(res & 0xffffffff); //that is the difference +} + +//// MULT +void recMULT_const() +{ + s64 res = (s64)g_cpuConstRegs[_Rs_].SL[0] * (s64)g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process); +void recMULTsuper(int info, int upper, int process) +{ + assert( !(info&PROCESS_EE_MMX) ); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + recWritebackHILO(info, 1, upper); +} + +//void recMULT_process(int info, int process) +//{ +// if( EEINST_ISLIVEMMX(XMMGPR_HI) || !(info&PROCESS_EE_MMX) ) { +// recMULTsuper(info, 0, process); +// } +// else { +// // EEREC_D isn't set +// int mmregd; +// +// if( _Rd_ ) { +// assert(EEREC_D == 0); +// mmregd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); +// +// if( mmregd < 0 ) { +// if( !(process&PROCESS_CONSTS) && ((g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE)||!EEINST_ISLIVEMMX(_Rs_)) ) { +// _freeMMXreg(EEREC_S); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_S].inuse = 1; +// mmxregs[EEREC_S].reg = _Rd_; +// mmxregs[EEREC_S].mode = MODE_WRITE; +// mmregd = EEREC_S; +// } +// else if( !(process&PROCESS_CONSTT) && ((g_pCurInstInfo->regs[_Rt_]&EEINST_LASTUSE)||!EEINST_ISLIVEMMX(_Rt_)) ) { +// _freeMMXreg(EEREC_T); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_T].inuse = 1; +// mmxregs[EEREC_T].reg = _Rd_; +// mmxregs[EEREC_T].mode = MODE_WRITE; +// mmregd = EEREC_T; +// } +// else mmregd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); +// } +// +// info |= PROCESS_EE_SET_D(mmregd); +// } +// recMULTUsuper(info, 0, process); +// } +// +// // sometimes _Rd_ can be const +// if( _Rd_ ) _eeOnWriteReg(_Rd_, 1); +//} + +void recMULT_(int info) +{ + //recMULT_process(info, 0); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, 0); + } + else recMULTUsuper(info, 0, 0); +} + +void recMULT_consts(int info) +{ + //recMULT_process(info, PROCESS_CONSTS); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTS); + } + else recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULT_constt(int info) +{ + //recMULT_process(info, PROCESS_CONSTT); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTT); + } + else recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't set XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI +EERECOMPILE_CODE0(MULT, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// MULTU +void recMULTU_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process) +{ + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( (info & PROCESS_EE_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + + if( !_Rd_ ) { + // need some temp reg + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + assert( EEREC_D == 0 ); + info |= PROCESS_EE_SET_D(t0reg); + } + + if( process & PROCESS_CONSTS ) { + u32* ptempmem = _eeGetConstReg(_Rs_); + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else if( process & PROCESS_CONSTT ) { + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else { + if( EEREC_D == EEREC_S ) PMULUDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PMULUDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQRtoR(EEREC_D, EEREC_T); + } + } + + recWritebackHILOMMX(info, EEREC_D, 1, upper); + + if( !_Rd_ ) _freeMMXreg(EEREC_D); + return; + } + + if( info & PROCESS_EE_MMX ) { + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_].UL[0], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + _deleteMMXreg(MMX_GPR+_Rd_, 0); + } + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_S); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EAX, EEREC_S); + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + } + + recWritebackHILO(info, 1, upper); +} + +void recMULTU_(int info) +{ + recMULTUsuper(info, 0, 0); +} + +void recMULTU_consts(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULTU_constt(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't specify XMMINFO_WRITELO or XMMINFO_WRITEHI, that is taken care of +EERECOMPILE_CODE0(MULTU, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULT1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULT1_(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, 0); + } + else recMULTUsuper(info, 1, 0); +} + +void recMULT1_consts(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTS); + } + else recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULT1_constt(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTT); + } + else recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULT1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULTU1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULTU1_(int info) +{ + recMULTUsuper(info, 1, 0); +} + +void recMULTU1_consts(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULTU1_constt(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULTU1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// DIV +void recDIV_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVsuper(int info, int sign, int upper, int process) +{ + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTT ) { + if( !g_cpuConstRegs[_Rt_].UL[0] ) + return; + MOV32ItoR( ECX, g_cpuConstRegs[_Rt_].UL[0] ); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + } + + if( process & PROCESS_CONSTS ) + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + + if( sign ) { + CDQ(); + IDIV32R( ECX ); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R( ECX ); + } + if( !(process & PROCESS_CONSTT) ) x86SetJ8( j8Ptr[ 0 ] ); + + // need to execute regardless of bad divide + recWritebackHILO(info, 0, upper); +} + +void recDIV_(int info) +{ + recDIVsuper(info, 1, 0, 0); +} + +void recDIV_consts(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTS); +} + +void recDIV_constt(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +//// DIVU +void recDIVU_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVU_(int info) +{ + recDIVsuper(info, 0, 0, 0); +} + +void recDIVU_consts(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTS); +} + +void recDIVU_constt(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +void recDIV1_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIV1_(int info) +{ + recDIVsuper(info, 1, 1, 0); +} + +void recDIV1_consts(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTS); +} + +void recDIV1_constt(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV1, XMMINFO_READS|XMMINFO_READT); + +void recDIVU1_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIVU1_(int info) +{ + recDIVsuper(info, 0, 1, 0); +} + +void recDIVU1_consts(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTS); +} + +void recDIVU1_constt(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU1, XMMINFO_READS|XMMINFO_READT); + +//do EEINST_SETSIGNEXT +REC_FUNC( MADD, _Rd_ ); + +__declspec(align(16)) static u32 s_MaddMask[] = { 0x80000000, 0, 0x80000000, 0 }; + +void recMADDU() +{ + _eeOnWriteReg(_Rd_, 1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + u64 result = ((u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + + // dadd + MOV32MtoR( EAX, (int)&cpuRegs.LO.UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.HI.UL[ 0 ] ); + ADD32ItoR( EAX, (u32)result&0xffffffff ); + ADC32ItoR( ECX, (u32)(result>>32) ); + CDQ(); + if( _Rd_) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); + return; + } + + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if ( GPR_IS_CONST1(_Rt_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + MOV32RtoR( ECX, EDX ); + ADD32MtoR( EAX, (u32)&cpuRegs.LO.UL[0] ); + ADC32MtoR( ECX, (u32)&cpuRegs.HI.UL[0] ); + CDQ(); + if( _Rd_ ) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); +} + +void recMADD1() +{ + SysPrintf("MADD1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( MADD1, _Rd_ ); +} + +void recMADDU1() +{ + SysPrintf("MADDU1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( MADDU1, _Rd_ ); +} + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MULT1, _Rd_ ); +REC_FUNC( MULTU1, _Rd_ ); +REC_FUNC( DIV1, _Rd_ ); +REC_FUNC( DIVU1, _Rd_ ); + +REC_FUNC( MADD, _Rd_ ); +REC_FUNC( MADDU, _Rd_ ); +REC_FUNC( MADD1, _Rd_ ); +REC_FUNC( MADDU1, _Rd_ ); + +#endif diff --git a/ix86-32/iR5900MultDiv.h b/ix86-32/iR5900MultDiv.h new file mode 100644 index 0000000000..243fd5c18a --- /dev/null +++ b/ix86-32/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/ix86-32/iR5900Shift.c b/ix86-32/iR5900Shift.c new file mode 100644 index 0000000000..51eae74ad6 --- /dev/null +++ b/ix86-32/iR5900Shift.c @@ -0,0 +1,1349 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#elif defined(EE_CONST_PROP) + +//// SLL +void recSLL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << _Sa_); +} + +void recSLLs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( g_pCurInstInfo->regs[_Rd_]&EEINST_MMX ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(rdreg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLL_(int info) +{ + recSLLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SLL); + +//// SRL +void recSRL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> _Sa_); +} + +void recSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + // rdreg already sign extended + PSLLQItoR(rdreg, 32); + PSRLQItoR(rdreg, 32+sa); +// t0reg = _allocMMXreg(-1, MMX_TEMP, 0); +// +// // it is a signed shift +// PSRLDItoR(rdreg, sa); +// MOVQRtoR(t0reg, rdreg); +// PSRADItoR(t0reg, 31); +// +// take lower dword of rdreg and lower dword of t0reg +// PUNPCKLDQRtoR(rdreg, t0reg); +// _freeMMXreg(t0reg); + } +} + +void recSRL_(int info) +{ + recSRLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRL); + +//// SRA +void recSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> _Sa_); +} + +void recSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SAR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(rdreg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(t0reg, rdreg); + + // swap regs + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recSRA_(int info) +{ + recSRAs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRA); + +//////////////////////////////////////////////////// +void recDSLL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << _Sa_); +} + +void recDSLLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa); +} + +void recDSLL_(int info) +{ + recDSLLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL); + +//////////////////////////////////////////////////// +void recDSRL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> _Sa_); +} + +void recDSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa); +} + +void recDSRL_(int info) +{ + recDSRLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL); + +//// DSRA +void recDSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> _Sa_); +} + +void recDSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLQItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + PSRADItoR(t0reg, sa); + PSRLQItoR(rdreg, sa); + + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + } +} + +void recDSRA_(int info) +{ + recDSRAs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA); + +///// DSLL32 +void recDSLL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (_Sa_+32)); +} + +void recDSLL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa+32); +} + +void recDSLL32_(int info) +{ + recDSLL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL32); + +//// DSRL32 +void recDSRL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (_Sa_+32)); +} + +void recDSRL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa+32); +} + +void recDSRL32_(int info) +{ + recDSRL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL32); + +//// DSRA32 +void recDSRA32_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> (_Sa_+32)); +} + +void recDSRA32s_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ( ); + if ( sa != 0 ) SAR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, 31); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + if( sa ) PSRADItoR(rdreg, sa); + PUNPCKHDQRtoR(rdreg, rdreg); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + if( sa ) { + PSRADItoR(rdreg, sa); + PSRADItoR(t0reg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + // better timing + PSRADItoR(rdreg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(t0reg, rdreg); + + // swap + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recDSRA32_(int info) +{ + recDSRA32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA32); + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +__declspec(align(16)) u32 s_sa[4] = {0x1f, 0, 0x3f, 0}; + +int recSetShiftV(int info, int* rsreg, int* rtreg, int* rdreg, int* rstemp, int forcemmx, int shift64) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + *rtreg = EEREC_T; + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_)) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else if( forcemmx || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + *rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + else { + return 0; + } + + if( *rtreg != *rdreg ) MOVQRtoR(*rdreg, *rtreg); + return 1; +} + +void recSetConstShiftV(int info, int* rsreg, int* rdreg, int* rstemp, int shift64) +{ + if( info & PROCESS_EE_MMX ) { + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_) ) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else { + _addNeededMMXreg(MMX_GPR+_Rd_); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + + _flushConstReg(_Rt_); +} + +void recMoveSignToRd(int info) +{ + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + + if( info & PROCESS_EE_MMX ) { + mmxregs[EEREC_D].inuse = 0; + } +} + +//// SLLV +void recSLLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSLLV_consts(int info) +{ + recSLLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info & PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRLV +void recSRLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRLV_consts(int info) +{ + recSRLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRAV +void recSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRAV_consts(int info) +{ + recSRAs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSLLV +void recDSLLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSLLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSLLs_(info, sa); + else recDSLL32s_(info, sa-32); +} + +void recDSLLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRLV +void recDSRLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRLs_(info, sa); + else recDSRL32s_(info, sa-32); +} + +void recDSRLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRAV +void recDSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s64)(g_cpuConstRegs[_Rt_].SD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRAV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRAs_(info, sa); + else recDSRA32s_(info, sa-32); +} + +void recDSRAV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recDSRA( void ) +{ + if( !_Rd_ ) return; //? + + if ( _Sa_ != 0 ) { + // it is a signed shift + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoR(MM1, MM0); + PSRADItoR(MM0, _Sa_); + PSRLQItoR(MM1, _Sa_); + + PUNPCKHDQRtoR(MM0, MM0); // shift to lower + // take lower dword of MM1 and lower dword of MM0 + + PUNPCKLDQRtoR(MM1, MM0); + + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM1); + } + else { + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSRA32(void) +{ + if( !_Rd_ ) return; //? + + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ(); + + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_ ); + } + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); +} + +//////////////////////////////////////////////////// +void recSLL( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHL32ItoR( EAX, _Sa_ ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHR32ItoR( EAX, _Sa_); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRA( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSLL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSLLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSRLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSLL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSLLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX,(int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSRLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +//////////////////////////////////////////////////// + + +//////////////////////////////////////////////////// +void recSLLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRAV( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +static u64 _sa = 0; +void recDSLLV( void ) +{ + if ( ! _Rd_ ) return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSLLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) +{ + if ( ! _Rd_ ) return; + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSRLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} +//////////////////////////////////////////////////////////////// +void recDSRAV( void ) +{ + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if ( _Rs_ != 0 ) { + PXORRtoR(MM1, MM1); + + // calc high bit + MOVQRtoR(MM2, MM0); + PUNPCKHDQRtoR(MM2, MM2); // shift to lower + PCMPGTDRtoR(MM1, MM2); + + // it is a signed shift + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOVD32RtoMMX(MM2, EAX); // amount to shift + NOT32R(EAX); + ADD32ItoR(EAX, 65); + + // right logical shift + PSRLQRtoR(MM0, MM2); + + // shift highest bit, 64 - eax + MOVD32RtoMMX(MM2, EAX); + PSLLQRtoR(MM1, MM2); // highest bits + + PORRtoR(MM0, MM1); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} +#endif diff --git a/ix86-32/iR5900Shift.h b/ix86-32/iR5900Shift.h new file mode 100644 index 0000000000..b7b3592691 --- /dev/null +++ b/ix86-32/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/memcpy_amd.cpp b/memcpy_amd.cpp new file mode 100644 index 0000000000..1ebd68d323 --- /dev/null +++ b/memcpy_amd.cpp @@ -0,0 +1,590 @@ +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ + +#include + +#include +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +// Inline assembly syntax for use with Visual C++ +extern "C" { + +#ifdef __WIN32__ +#include +#endif + +#include "ps2etypes.h" +#include "misc.h" + +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeMMXRegs(save) if( g_EEFreezeRegs && CHECK_EEREC ) { FreezeMMXRegs_(save); } +#define FreezeXMMRegs(save) if( g_EEFreezeRegs && CHECK_EEREC ) { FreezeXMMRegs_(save); } + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalMMXSaved; + +void checkregs() +{ + assert( !g_globalMMXLocked || g_globalMMXSaved ); +} +#endif + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ + FreezeMMXRegs(1); + +#ifdef _DEBUG + __asm call checkregs +#endif + + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; don't align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that's faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb's + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd's + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it's in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd's + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, let's leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcpy implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +int memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + mov ecx, cmpsize + mov edi, src1 + mov esi, src2 + mov ebx, ecx + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edi+16] + pcmpeqd mm3, [edi+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + + sub ecx, 32 + add esi, 32 + add edi, 32 + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pcmpeqd mm2, [edi+16] + pcmpeqd mm3, [edi+24] + pand mm0, mm1 + pcmpeqd mm4, [edi+32] + pand mm0, mm2 + pcmpeqd mm5, [edi+40] + pand mm0, mm3 + pcmpeqd mm6, [edi+48] + pand mm0, mm4 + pcmpeqd mm7, [edi+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edi, 64 + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pcmpeqd mm2, [edi+16] + pcmpeqd mm3, [edi+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edi, 32 + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pcmpeqd mm2, [edi+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + xor edx, edx + cmp eax, 0xff + cmove eax, edx + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + xor edx, edx + cmp eax, 0xff + cmove eax, edx + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov ebx, [esi+4] + cmp eax, [edi] + je Next + mov eax, 1 + jmp End + +Next: + cmp ebx, [edi+4] + je Done + mov eax, 1 + jmp End + +Done: + xor eax, eax + +End: + emms + } +} + + +// returns the xor of all elements, cmpsize has to be mult of 8 +void memxor_mmx(void* dst, const void* src1, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + mov ecx, cmpsize + mov esi, src1 + mov ebx, ecx + mov edx, dst + + cmp ecx, 64 + jl Setup4 + + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + sub ecx, 64 + add esi, 64 + cmp ecx, 64 + jl End8 + +Cmp8: + pxor mm0, [esi] + pxor mm1, [esi+8] + pxor mm2, [esi+16] + pxor mm3, [esi+24] + pxor mm4, [esi+32] + pxor mm5, [esi+40] + pxor mm6, [esi+48] + pxor mm7, [esi+56] + + sub ecx, 64 + add esi, 64 + cmp ecx, 64 + jge Cmp8 + +End8: + pxor mm0, mm4 + pxor mm1, mm5 + pxor mm2, mm6 + pxor mm3, mm7 + + cmp ecx, 32 + jl End4 + pxor mm0, [esi] + pxor mm1, [esi+8] + pxor mm2, [esi+16] + pxor mm3, [esi+24] + sub ecx, 32 + add esi, 32 + jmp End4 + +Setup4: + cmp ecx, 32 + jl Setup2 + + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + sub ecx, 32 + add esi, 32 + +End4: + pxor mm0, mm2 + pxor mm1, mm3 + + cmp ecx, 16 + jl End2 + pxor mm0, [esi] + pxor mm1, [esi+8] + sub ecx, 16 + add esi, 16 + jmp End2 + +Setup2: + cmp ecx, 16 + jl Setup1 + + movq mm0, [esi] + movq mm1, [esi+8] + sub ecx, 16 + add esi, 16 + +End2: + pxor mm0, mm1 + + cmp ecx, 8 + jl End1 + pxor mm0, [esi] +End1: + movq [edx], mm0 + jmp End + +Setup1: + movq mm0, [esi] + movq [edx], mm0 +End: + emms + } +} + +} \ No newline at end of file diff --git a/pcl/pcl.c b/pcl/pcl.c new file mode 100644 index 0000000000..b871909f1f --- /dev/null +++ b/pcl/pcl.c @@ -0,0 +1,490 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#include +#include +#include "pcl_config.h" +#include "pcl.h" + + +#if defined(CO_USE_UCONEXT) +#include + +typedef ucontext_t co_core_ctx_t; +#else +#include + +typedef jmp_buf co_core_ctx_t; +#endif + +#if defined(CO_USE_SIGCONTEXT) +#include +#endif + + +/* + * The following value must be power of two ( N^2 ). + */ +#define CO_STK_ALIGN 256 +#define CO_STK_COROSIZE ((sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1)) +#define CO_MIN_SIZE (4 * 1024) + + +typedef struct s_co_ctx { + co_core_ctx_t cc; +} co_ctx_t; + +typedef struct s_coroutine { + co_ctx_t ctx; + int alloc; + struct s_coroutine *caller; + struct s_coroutine *restarget; + void (*func)(void *); + void *data; +} coroutine; + + +static coroutine co_main; +static coroutine *co_curr = &co_main; +static coroutine *co_dhelper; + +#if defined(CO_USE_SIGCONTEXT) + +static volatile int ctx_called; +static co_ctx_t *ctx_creating; +static void *ctx_creating_func; +static sigset_t ctx_creating_sigs; +static co_ctx_t ctx_trampoline; +static co_ctx_t ctx_caller; + +#endif /* #if defined(CO_USE_SIGCONTEXT) */ + + + +static int co_ctx_sdir(unsigned long psp) { + int nav = 0; + unsigned long csp = (unsigned long) &nav; + + return psp > csp ? -1: +1; +} + + +static int co_ctx_stackdir(void) { + int cav = 0; + + return co_ctx_sdir((unsigned long) &cav); +} + + +#if defined(CO_USE_UCONEXT) + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + + if (getcontext(&ctx->cc)) + return -1; + + ctx->cc.uc_link = NULL; + + ctx->cc.uc_stack.ss_sp = stkbase; + ctx->cc.uc_stack.ss_size = stksiz - sizeof(long); + ctx->cc.uc_stack.ss_flags = 0; + + makecontext(&ctx->cc, func, 1); + + return 0; +} + + +static void co_switch_context(co_ctx_t *octx, co_ctx_t *nctx) { + + if (swapcontext(&octx->cc, &nctx->cc) < 0) { + fprintf(stderr, "[PCL] Context switch failed: curr=%p\n", + co_curr); + exit(1); + } +} + +#else /* #if defined(CO_USE_UCONEXT) */ + +#if defined(CO_USE_SIGCONTEXT) + +/* + * This code comes from the GNU Pth implementation and uses the + * sigstack/sigaltstack() trick. + * + * The ingenious fact is that this variant runs really on _all_ POSIX + * compliant systems without special platform kludges. But be _VERY_ + * carefully when you change something in the following code. The slightest + * change or reordering can lead to horribly broken code. Really every + * function call in the following case is intended to be how it is, doubt + * me... + * + * For more details we strongly recommend you to read the companion + * paper ``Portable Multithreading -- The Signal Stack Trick for + * User-Space Thread Creation'' from Ralf S. Engelschall. + */ + +static void co_ctx_bootstrap(void) { + co_ctx_t * volatile ctx_starting; + void (* volatile ctx_starting_func)(void); + + /* + * Switch to the final signal mask (inherited from parent) + */ + sigprocmask(SIG_SETMASK, &ctx_creating_sigs, NULL); + + /* + * Move startup details from static storage to local auto + * variables which is necessary because it has to survive in + * a local context until the thread is scheduled for real. + */ + ctx_starting = ctx_creating; + ctx_starting_func = (void (*)(void)) ctx_creating_func; + + /* + * Save current machine state (on new stack) and + * go back to caller until we're scheduled for real... + */ + if (!setjmp(ctx_starting->cc)) + longjmp(ctx_caller.cc, 1); + + /* + * The new thread is now running: GREAT! + * Now we just invoke its init function.... + */ + ctx_starting_func(); + + fprintf(stderr, "[PCL] Hmm, you really shouldn't reach this point: curr=%p\n", + co_curr); + exit(1); +} + + +static void co_ctx_trampoline(int sig) { + /* + * Save current machine state and _immediately_ go back with + * a standard "return" (to stop the signal handler situation) + * to let him remove the stack again. Notice that we really + * have do a normal "return" here, or the OS would consider + * the thread to be running on a signal stack which isn't + * good (for instance it wouldn't allow us to spawn a thread + * from within a thread, etc.) + */ + if (!setjmp(ctx_trampoline.cc)) { + ctx_called = 1; + return; + } + + /* + * Ok, the caller has longjmp'ed back to us, so now prepare + * us for the real machine state switching. We have to jump + * into another function here to get a new stack context for + * the auto variables (which have to be auto-variables + * because the start of the thread happens later). + */ + co_ctx_bootstrap(); +} + + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + struct sigaction sa; + struct sigaction osa; + sigset_t osigs; + sigset_t sigs; +#if defined(CO_HAS_SIGSTACK) + struct sigstack ss; + struct sigstack oss; +#elif defined(CO_HAS_SIGALTSTACK) + struct sigaltstack ss; + struct sigaltstack oss; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Preserve the SIGUSR1 signal state, block SIGUSR1, + * and establish our signal handler. The signal will + * later transfer control onto the signal stack. + */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGUSR1); + sigprocmask(SIG_BLOCK, &sigs, &osigs); + sa.sa_handler = co_ctx_trampoline; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_ONSTACK; + if (sigaction(SIGUSR1, &sa, &osa) != 0) + return -1; + + /* + * Set the new stack. + * + * For sigaltstack we're lucky [from sigaltstack(2) on + * FreeBSD 3.1]: ``Signal stacks are automatically adjusted + * for the direction of stack growth and alignment + * requirements'' + * + * For sigstack we have to decide ourself [from sigstack(2) + * on Solaris 2.6]: ``The direction of stack growth is not + * indicated in the historical definition of struct sigstack. + * The only way to portably establish a stack pointer is for + * the application to determine stack growth direction.'' + */ +#if defined(CO_HAS_SIGALTSTACK) + ss.ss_sp = stkbase; + ss.ss_size = stksiz - sizeof(long); + ss.ss_flags = 0; + if (sigaltstack(&ss, &oss) < 0) + return -1; +#elif defined(CO_HAS_SIGSTACK) + if (co_ctx_stackdir() < 0) + ss.ss_sp = (stkbase + stksiz - sizeof(long)); + else + ss.ss_sp = stkbase; + ss.ss_onstack = 0; + if (sigstack(&ss, &oss) < 0) + return -1; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Now transfer control onto the signal stack and set it up. + * It will return immediately via "return" after the setjmp() + * was performed. Be careful here with race conditions. The + * signal can be delivered the first time sigsuspend() is + * called. + */ + ctx_called = 0; + kill(getpid(), SIGUSR1); + sigfillset(&sigs); + sigdelset(&sigs, SIGUSR1); + while (!ctx_called) + sigsuspend(&sigs); + + /* + * Inform the system that we are back off the signal stack by + * removing the alternative signal stack. Be careful here: It + * first has to be disabled, before it can be removed. + */ +#if defined(CO_HAS_SIGALTSTACK) + sigaltstack(NULL, &ss); + ss.ss_flags = SS_DISABLE; + if (sigaltstack(&ss, NULL) < 0) + return -1; + sigaltstack(NULL, &ss); + if (!(ss.ss_flags & SS_DISABLE)) + return -1; + if (!(oss.ss_flags & SS_DISABLE)) + sigaltstack(&oss, NULL); +#elif defined(CO_HAS_SIGSTACK) + if (sigstack(&oss, NULL)) + return -1; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Restore the old SIGUSR1 signal handler and mask + */ + sigaction(SIGUSR1, &osa, NULL); + sigprocmask(SIG_SETMASK, &osigs, NULL); + + /* + * Set creation information. + */ + ctx_creating = ctx; + ctx_creating_func = func; + memcpy(&ctx_creating_sigs, &osigs, sizeof(sigset_t)); + + /* + * Now enter the trampoline again, but this time not as a signal + * handler. Instead we jump into it directly. + */ + if (!setjmp(ctx_caller.cc)) + longjmp(ctx_trampoline.cc, 1); + + return 0; +} + +#else /* #if defined(CO_USE_SIGCONTEXT) */ + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + char *stack; + + stack = stkbase + stksiz - sizeof(long); + + setjmp(ctx->cc); + +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(JB_PC) && defined(JB_SP) + ctx->cc[0].__jmpbuf[JB_PC] = (int) func; + ctx->cc[0].__jmpbuf[JB_SP] = (int) stack; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(__mc68000__) + ctx->cc[0].__jmpbuf[0].__aregs[0] = (long) func; + ctx->cc[0].__jmpbuf[0].__sp = (int *) stack; +#elif defined(__GNU_LIBRARY__) && defined(__i386__) + ctx->cc[0].__jmpbuf[0].__pc = func; + ctx->cc[0].__jmpbuf[0].__sp = stack; +#elif defined(_WIN32) && defined(_MSC_VER) + ((_JUMP_BUFFER *) &ctx->cc)->Eip = (long) func; + ((_JUMP_BUFFER *) &ctx->cc)->Esp = (long) stack; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && (defined(__powerpc64__) || defined(__powerpc__)) + ctx->cc[0].__jmpbuf[JB_LR] = (int) func; + ctx->cc[0].__jmpbuf[JB_GPR1] = (int) stack; +#else +#error "PCL: Unsupported setjmp/longjmp platform. Please report to " +#endif + + return 0; +} + +#endif /* #if defined(CO_USE_SIGCONTEXT) */ + + +static void co_switch_context(co_ctx_t *octx, co_ctx_t *nctx) { + + if (!setjmp(octx->cc)) + longjmp(nctx->cc, 1); +} + +#endif /* #if defined(CO_USE_UCONEXT) */ + + +static void co_runner(void) { + coroutine *co = co_curr; + + co->restarget = co->caller; + co->func(co->data); + co_exit(); +} + + +coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size) { + int alloc = 0, r = CO_STK_COROSIZE; + coroutine *co; + + if ((size &= ~(sizeof(long) - 1)) < CO_MIN_SIZE) + return NULL; + if (!stack) { + size = (size + sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1); + stack = malloc(size); + if (!stack) + return NULL; + alloc = size; + } + co = stack; + stack = (char *) stack + CO_STK_COROSIZE; + co->alloc = alloc; + co->func = func; + co->data = data; + if (co_set_context(&co->ctx, co_runner, stack, size - CO_STK_COROSIZE) < 0) { + if (alloc) + free(co); + return NULL; + } + + return (coroutine_t) co; +} + + +void co_delete(coroutine_t coro) { + coroutine *co = (coroutine *) coro; + + if (co == co_curr) { + fprintf(stderr, "[PCL] Cannot delete itself: curr=%p\n", + co_curr); + exit(1); + } + if (co->alloc) + free(co); +} + + +void co_call(coroutine_t coro) { + coroutine *co = (coroutine *) coro, *oldco = co_curr; + + co->caller = co_curr; + co_curr = co; + + co_switch_context(&oldco->ctx, &co->ctx); +} + + +void co_resume(void) { + + co_call(co_curr->restarget); + co_curr->restarget = co_curr->caller; +} + + +static void co_del_helper(void *data) { + coroutine *cdh; + + for (;;) { + cdh = co_dhelper; + co_dhelper = NULL; + co_delete(co_curr->caller); + co_call((coroutine_t) cdh); + if (!co_dhelper) { + fprintf(stderr, "[PCL] Resume to delete helper coroutine: curr=%p\n", + co_curr); + exit(1); + } + } +} + + +void co_exit_to(coroutine_t coro) { + coroutine *co = (coroutine *) coro; + static coroutine *dchelper = NULL; + static char stk[CO_MIN_SIZE]; + + if (!dchelper && + !(dchelper = co_create(co_del_helper, NULL, stk, sizeof(stk)))) { + fprintf(stderr, "[PCL] Unable to create delete helper coroutine: curr=%p\n", + co_curr); + exit(1); + } + + co_dhelper = co; + + co_call((coroutine_t) dchelper); + + fprintf(stderr, "[PCL] Stale coroutine called: curr=%p\n", + co_curr); + exit(1); +} + + +void co_exit(void) { + + co_exit_to((coroutine_t) co_curr->restarget); +} + + +coroutine_t co_current(void) { + + return (coroutine_t) co_curr; +} + diff --git a/pcl/pcl.h b/pcl/pcl.h new file mode 100644 index 0000000000..122112e402 --- /dev/null +++ b/pcl/pcl.h @@ -0,0 +1,49 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#if !defined(PCL_H) +#define PCL_H + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef void *coroutine_t; + + +coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size); +void co_delete(coroutine_t coro); +void co_call(coroutine_t coro); +void co_resume(void); +void co_exit_to(coroutine_t coro); +void co_exit(void); +coroutine_t co_current(void); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/pcl/pcl_config.h b/pcl/pcl_config.h new file mode 100644 index 0000000000..9c37c64c2b --- /dev/null +++ b/pcl/pcl_config.h @@ -0,0 +1,60 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#if !defined(PCL_CONFIG_H) +#define PCL_CONFIG_H + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif /* #if defined(HAVE_CONFIG_H) */ + + +#if defined(HAVE_GETCONTEXT) && defined(HAVE_MAKECONTEXT) && defined(HAVE_SWAPCONTEXT) + +/* + * Use this if the system has a working getcontext/makecontext/swapcontext + * implementation. + */ +#define CO_USE_UCONEXT + +#elif defined(HAVE_SIGACTION) + +/* + * Use this to have the generic signal implementation ( not working on + * Windows ). Suggested on generic Unix implementations or on Linux with + * CPU different from x86 family. + */ +#define CO_USE_SIGCONTEXT + +/* + * Use this in conjuction with CO_USE_SIGCONTEXT to use the sigaltstack + * environment ( suggested when CO_USE_SIGCONTEXT is defined ). + */ +#if defined(HAVE_SIGALTSTACK) +#define CO_HAS_SIGALTSTACK +#endif + +#endif + + +#endif + diff --git a/pcsxAbout.bmp b/pcsxAbout.bmp new file mode 100644 index 0000000000..da33bb08f4 Binary files /dev/null and b/pcsxAbout.bmp differ diff --git a/windows/AboutDlg.c b/windows/AboutDlg.c new file mode 100644 index 0000000000..fa214a7bd8 --- /dev/null +++ b/windows/AboutDlg.c @@ -0,0 +1,65 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "resource.h" +#include "AboutDlg.h" +#include "Common.h" + +#ifdef __MINGW32__ +#define IDC_STATIC (-1) +#endif + +#ifdef __MSCW32__ +#define IDC_STATIC (-1) +#endif + +HWND hW; +HBITMAP hBMP, hSilverBMP; + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER)); + + hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP, + 230, 10, 211, 110, hDlg, (HMENU)IDC_STATIC, GetModuleHandle(NULL), NULL); + SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP); + + SetWindowText(hDlg, _("About")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_TEXT), _("PCSX2 EMU\n")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_AUTHORS), _(LabelAuthors)); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_GREETS), _(LabelGreets)); + return TRUE; + + case WM_COMMAND: + switch(wParam) { + case IDOK: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/windows/AboutDlg.h b/windows/AboutDlg.h new file mode 100644 index 0000000000..1a209be81a --- /dev/null +++ b/windows/AboutDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_ABOUTDLG_H_ +#define _PCSX2_ABOUTDLG_H_ + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif diff --git a/windows/Cdrom02.ico b/windows/Cdrom02.ico new file mode 100644 index 0000000000..07588baeaa Binary files /dev/null and b/windows/Cdrom02.ico differ diff --git a/windows/ConfigDlg.c b/windows/ConfigDlg.c new file mode 100644 index 0000000000..777b109c13 --- /dev/null +++ b/windows/ConfigDlg.c @@ -0,0 +1,499 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include //2002-09-22 (Florin) +#include "common.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +#define ComboAddPlugin(hw, str) { \ + sprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff); \ + lp = (char *)malloc(strlen(FindData.cFileName)+8); \ + sprintf(lp, "%s", FindData.cFileName); \ + i = ComboBox_AddString(hw, tmpStr); \ + ComboBox_SetItemData(hw, i, lp); \ + if (stricmp(str, lp)==0) \ + ComboBox_SetCurSel(hw, i); \ +} + +BOOL OnConfigureDialog(HWND hW) { + WIN32_FIND_DATA FindData; + HANDLE Find; + HANDLE Lib; + _PS2EgetLibType PS2E_GetLibType; + _PS2EgetLibName PS2E_GetLibName; + _PS2EgetLibVersion2 PS2E_GetLibVersion2; + HWND hWC_GS=GetDlgItem(hW,IDC_LISTGS); + HWND hWC_PAD1=GetDlgItem(hW,IDC_LISTPAD1); + HWND hWC_PAD2=GetDlgItem(hW,IDC_LISTPAD2); + HWND hWC_SPU2=GetDlgItem(hW,IDC_LISTSPU2); + HWND hWC_CDVD=GetDlgItem(hW,IDC_LISTCDVD); + HWND hWC_DEV9=GetDlgItem(hW,IDC_LISTDEV9); + HWND hWC_USB=GetDlgItem(hW,IDC_LISTUSB); + HWND hWC_FW=GetDlgItem(hW,IDC_LISTFW); + HWND hWC_BIOS=GetDlgItem(hW,IDC_LISTBIOS); + char tmpStr[256]; + char *lp; + int i; + + strcpy(tmpStr, Config.PluginsDir); + strcat(tmpStr, "*.dll"); + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + sprintf(tmpStr,"%s%s", Config.PluginsDir, FindData.cFileName); + Lib = LoadLibrary(tmpStr); + if (Lib == NULL) { SysPrintf("%s: %d\n", tmpStr, GetLastError()); continue; } + + PS2E_GetLibType = (_PS2EgetLibType) GetProcAddress((HMODULE)Lib,"PS2EgetLibType"); + PS2E_GetLibName = (_PS2EgetLibName) GetProcAddress((HMODULE)Lib,"PS2EgetLibName"); + PS2E_GetLibVersion2 = (_PS2EgetLibVersion2) GetProcAddress((HMODULE)Lib,"PS2EgetLibVersion2"); + + if (PS2E_GetLibType != NULL && PS2E_GetLibName != NULL && PS2E_GetLibVersion2 != NULL) { + u32 version; + long type; + + type = PS2E_GetLibType(); + if (type & PS2E_LT_GS) { + version = PS2E_GetLibVersion2(PS2E_LT_GS); + if ( ((version >> 16)&0xff) == PS2E_GS_VERSION) { + ComboAddPlugin(hWC_GS, Config.GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, 0xff&(version >> 16), PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)GetProcAddress((HMODULE)Lib, "PADquery"); + version = PS2E_GetLibVersion2(PS2E_LT_PAD); + if (((version >> 16)&0xff) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(hWC_PAD1, Config.PAD1); + if (query() & 0x2) + ComboAddPlugin(hWC_PAD2, Config.PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2E_GetLibVersion2(PS2E_LT_SPU2); + if ( ((version >> 16)&0xff) == PS2E_SPU2_VERSION) { + ComboAddPlugin(hWC_SPU2, Config.SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2E_GetLibVersion2(PS2E_LT_CDVD); + if (((version >> 16)&0xff) == PS2E_CDVD_VERSION) { + ComboAddPlugin(hWC_CDVD, Config.CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2E_GetLibVersion2(PS2E_LT_DEV9); + if (((version >> 16)&0xff) == PS2E_DEV9_VERSION) { + ComboAddPlugin(hWC_DEV9, Config.DEV9); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2E_GetLibVersion2(PS2E_LT_USB); + if (((version >> 16)&0xff) == PS2E_USB_VERSION) { + ComboAddPlugin(hWC_USB, Config.USB); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2E_GetLibVersion2(PS2E_LT_FW); + if (((version >> 16)&0xff) == PS2E_FW_VERSION) { + ComboAddPlugin(hWC_FW, Config.FW); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_FW_VERSION); + } + } + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + +// BIOS + + /*lp=(char *)malloc(strlen("HLE") + 1); + sprintf(lp, "HLE"); + i=ComboBox_AddString(hWC_BIOS, _("Internal HLE Bios")); + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, lp)==0) + ComboBox_SetCurSel(hWC_BIOS, i);*/ + + strcpy(tmpStr, Config.BiosDir); + strcat(tmpStr, "*"); + Find=FindFirstFile(tmpStr, &FindData); + + do { + char description[50]; //2002-09-22 (Florin) + if (Find==INVALID_HANDLE_VALUE) break; + if (!strcmp(FindData.cFileName, ".")) continue; + if (!strcmp(FindData.cFileName, "..")) continue; +// if (FindData.nFileSizeLow < 1024 * 512) continue; + if (FindData.nFileSizeLow > 1024 * 4096) continue; //2002-09-22 (Florin) + if (!IsBIOS(FindData.cFileName, description)) continue;//2002-09-22 (Florin) + lp = (char *)malloc(strlen(FindData.cFileName)+8); + sprintf(lp, "%s", (char *)FindData.cFileName); + i = ComboBox_AddString(hWC_BIOS, description); //2002-09-22 (Florin) modified + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, FindData.cFileName)==0) + ComboBox_SetCurSel(hWC_BIOS, i); + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + + if (ComboBox_GetCurSel(hWC_GS) == -1) + ComboBox_SetCurSel(hWC_GS, 0); + if (ComboBox_GetCurSel(hWC_PAD1) == -1) + ComboBox_SetCurSel(hWC_PAD1, 0); + if (ComboBox_GetCurSel(hWC_PAD2) == -1) + ComboBox_SetCurSel(hWC_PAD2, 0); + if (ComboBox_GetCurSel(hWC_SPU2) == -1) + ComboBox_SetCurSel(hWC_SPU2, 0); + if (ComboBox_GetCurSel(hWC_CDVD) == -1) + ComboBox_SetCurSel(hWC_CDVD, 0); + if (ComboBox_GetCurSel(hWC_DEV9) == -1) + ComboBox_SetCurSel(hWC_DEV9, 0); + if (ComboBox_GetCurSel(hWC_USB) == -1) + ComboBox_SetCurSel(hWC_USB, 0); + if (ComboBox_GetCurSel(hWC_FW) == -1) + ComboBox_SetCurSel(hWC_FW, 0); + if (ComboBox_GetCurSel(hWC_BIOS) == -1) + ComboBox_SetCurSel(hWC_BIOS, 0); + + return TRUE; +} + +#define CleanCombo(item) \ + hWC = GetDlgItem(hW, item); \ + iCnt = ComboBox_GetCount(hWC); \ + for (i=0; i +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + char cpuspeedc[20]; + char features[256]; + u32 newopts; + + switch(uMsg) { + case WM_INITDIALOG: + SetWindowText(hW, _("Cpu Config")); + SetDlgItemText(hW, IDC_VENDORINPUT,cpuinfo.x86ID ); + SetDlgItemText(hW, IDC_FAMILYINPUT, cpuinfo.x86Fam); + sprintf(cpuspeedc,"%d MHZ",cpuinfo.cpuspeed); + SetDlgItemText(hW, IDC_CPUSPEEDINPUT, cpuspeedc); + //features[0]=':'; + //strcat(features,""); + strcpy(features,""); + if(cpucaps.hasMultimediaExtensions) strcat(features,"MMX"); + if(cpucaps.hasStreamingSIMDExtensions) strcat(features,",SSE"); + if(cpucaps.hasStreamingSIMD2Extensions) strcat(features,",SSE2"); + if(cpucaps.has3DNOWInstructionExtensions) strcat(features,",3DNOW"); + if(cpucaps.has3DNOWInstructionExtensionsExt)strcat(features,",3DNOW+"); + if(cpucaps.hasAMD64BitArchitecture) strcat(features,",x86-64"); + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + if(!cpucaps.hasStreamingSIMDExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILERVU),FALSE);//disable checkbox if no SSE2 found + Config.Options &= (PCSX2_VU0REC|PCSX2_VU1REC);//disable the config just in case + } + if(!cpucaps.hasMultimediaExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILER),FALSE); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC|PCSX2_COP2REC);//return to interpreter mode + + } + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + + CheckDlgButton(hW, IDC_CPU_EEREC, !!CHECK_EEREC); + CheckDlgButton(hW, IDC_CPU_VU0REC, !!CHECK_VU0REC); + CheckDlgButton(hW, IDC_CPU_VU1REC, !!CHECK_VU1REC); + + CheckDlgButton(hW, IDC_CPU_GSMULTI, !!CHECK_MULTIGS); + CheckDlgButton(hW, IDC_CPU_MULTI, !!CHECK_DUALCORE); + CheckDlgButton(hW, IDC_CPU_FRAMELIMIT, !!CHECK_FRAMELIMIT); + CheckDlgButton(hW, IDC_CPU_FORCEABS, !!CHECK_FORCEABS); + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + + case IDOK: + Cpu->Shutdown(); + vu0Shutdown(); + vu1Shutdown(); + + newopts = 0; + + if( SendDlgItemMessage(hW,IDC_CPU_EEREC,BM_GETCHECK,0,0) ) newopts |= PCSX2_EEREC; + if( SendDlgItemMessage(hW,IDC_CPU_VU0REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU0REC; + if( SendDlgItemMessage(hW,IDC_CPU_VU1REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU1REC; + + if( SendDlgItemMessage(hW,IDC_CPU_GSMULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_GSMULTITHREAD; + if( SendDlgItemMessage(hW,IDC_CPU_MULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_DUALCORE; + if( SendDlgItemMessage(hW,IDC_CPU_FRAMELIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT; + if( SendDlgItemMessage(hW,IDC_CPU_FORCEABS,BM_GETCHECK,0,0) ) newopts |= PCSX2_FORCEABS; + + if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) { + Config.Options = newopts; + SaveConfig(); + MessageBox(NULL, "Restart Pcsx2", "Query", MB_OK); + exit(0); + } + + if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC; + + Config.Options = newopts; + + UpdateVSyncRate(); + SaveConfig(); + + cpuRestartCPU(); + EndDialog(hW, TRUE); + return TRUE; + } + } + return FALSE; +} diff --git a/windows/DebugMemory.c b/windows/DebugMemory.c new file mode 100644 index 0000000000..cf79747a1a --- /dev/null +++ b/windows/DebugMemory.c @@ -0,0 +1,239 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "resource.h" + + +unsigned long memory_addr; +BOOL mem_inupdate = FALSE; +HWND memoryhWnd,hWnd_memscroll,hWnd_memorydump; +unsigned long memory_patch; +unsigned long data_patch; + +///MEMORY DUMP +unsigned char Debug_Read8(unsigned long addr)//just for anycase.. +{ +#ifdef __MSCW32__ + __try + { +#endif + u8 val8; + memRead8(addr, &val8); + return val8; +#ifdef __MSCW32__ + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return 0; + } +#endif +} + + +void RefreshMemory(void) +{ + int x, y; + unsigned long addr; + unsigned char b; + + char buf[128], text[32], temp[8]; + + + + addr = memory_addr; + + if (!mem_inupdate) + { + sprintf(buf, "%08X", addr); + SetDlgItemText(memoryhWnd, IDC_MEMORY_ADDR, buf); + } + + SendMessage(hWnd_memorydump, LB_RESETCONTENT, 0, 0); + + for (y = 0; y < 21; y++) + { + memset(text, 0, 32); + sprintf(buf, "%08X: ", addr); + + for (x = 0; x < 16; x++) + { + b = Debug_Read8(addr++); + + sprintf(temp, "%02X ", b); + strcat(buf, temp); + + if (b < 32 || b > 127) b = 32; + sprintf(temp, "%c", b); + strcat(text, temp); + + + if (x == 7) strcat(buf, " "); + } + + strcat(buf, " "); + strcat(buf, text); + + SendMessage(hWnd_memorydump, LB_ADDSTRING, 0, (LPARAM)buf); + } +} + + +BOOL APIENTRY DumpMemProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], buf[128]; + u32 start_pc, end_pc, addr; + u8 data; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMPMEM_START, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_END, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, "dump.raw"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMPMEM_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, fname, 128); + fp = fopen(fname, "wb"); + if (fp == NULL) + { + SysMessage("Can't open file '%s' for writing!\n", fname); + } + else + { + for (addr = start_pc; addr < end_pc; addr ++) { + memRead8( addr, &data ); + fwrite(&data, 1, 1, fp); + } + + fclose(fp); + } + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + + + +BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + char buf[16]; + switch (message) + { + case WM_INITDIALOG: + memory_addr = cpuRegs.pc; + sprintf(buf, "%08X", memory_addr); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + memory_patch= 0; + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf); + data_patch=0; + sprintf(buf, "%08X", data_patch); + SetDlgItemText(hDlg, IDC_DATA_PATCH, buf); + hWnd_memorydump = GetDlgItem(hDlg, IDC_MEMORY_DUMP); + hWnd_memscroll = GetDlgItem(hDlg, IDC_MEM_SCROLL); + + + + SendMessage(hWnd_memorydump, LB_INITSTORAGE, 11, 1280); + SendMessage(hWnd_memscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_memscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + RefreshMemory(); + return TRUE; + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + case SB_LINEDOWN: memory_addr += 0x00000010; RefreshMemory(); break; + case SB_LINEUP: memory_addr -= 0x00000010; RefreshMemory(); break; + case SB_PAGEDOWN: memory_addr += 0x00000150; RefreshMemory(); break; + case SB_PAGEUP: memory_addr -= 0x00000150; RefreshMemory(); break; + } + + return TRUE; + + case WM_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + + + case WM_COMMAND: + if (HIWORD(wParam) == EN_UPDATE) + { + mem_inupdate = TRUE; + GetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf, 9); + buf[8] = 0; + + sscanf(buf, "%x", &memory_addr); + RefreshMemory(); + mem_inupdate = FALSE; + return TRUE; + } + + switch (LOWORD(wParam)) { + case IDC_PATCH: + GetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf, 9);//32bit address + buf[8] = 0; + sscanf(buf, "%x", &memory_patch); + GetDlgItemText(hDlg, IDC_DATA_PATCH, buf, 9);//32 bit data only for far + buf[8] = 0; + sscanf(buf, "%x", &data_patch); + memWrite32( memory_patch, data_patch ); + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + RefreshMemory(); + return TRUE; + + case IDC_DUMPRAW: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMPMEM), hDlg, (DLGPROC)DumpMemProc); + + return TRUE; + + case IDC_MEMORY_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + + return FALSE; +} \ No newline at end of file diff --git a/windows/Debugger.c b/windows/Debugger.c new file mode 100644 index 0000000000..3164c9d53d --- /dev/null +++ b/windows/Debugger.c @@ -0,0 +1,562 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "Common.h" +#include "win32.h" +#include "PsxMem.h" +#include "R3000A.h" + +extern void (*IOP_DEBUG_BSC[64])(char *buf); +extern void UpdateR5900op(); +void RefreshIOPDebugger(void); +extern int ISR3000A;//for disasm +HWND hWnd_debugdisasm, hWnd_debugscroll,hWnd_IOP_debugdisasm, hWnd_IOP_debugscroll; +unsigned long DebuggerPC = 0; +HWND hRegDlg;//for debug registers.. +HWND debughWnd; +unsigned long DebuggerIOPPC=0; +HWND hIOPDlg;//IOP debugger + + +void RefreshDebugAll()//refresh disasm and register window +{ + RefreshDebugger(); + RefreshIOPDebugger(); + UpdateRegs(); + + +} + +void MakeDebugOpcode(void) +{ + memRead32( opcode_addr, &cpuRegs.code ); +} + +void MakeIOPDebugOpcode(void) +{ + psxRegs.code = PSXMu32( opcode_addr); +} + +BOOL HasBreakpoint() +{ + int t; + + for (t = 0; t < NUM_BREAKPOINTS; t++) + { + switch (bkpt_regv[t].type) { + case 1: // exec + if (cpuRegs.pc == bkpt_regv[t].value) return TRUE; + break; + + case 2: // count + if ((cpuRegs.cycle - 10) <= bkpt_regv[t].value && + (cpuRegs.cycle + 10) >= bkpt_regv[t].value) return TRUE; + break; + } + } + return FALSE; + +} +BOOL APIENTRY JumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + unsigned long temp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_JUMP_PC, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_JUMP_PC, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &temp); + + temp &= 0xFFFFFFFC; + DebuggerPC = temp - 0x00000038; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +extern void EEDumpRegs(FILE * fp); +extern void IOPDumpRegs(FILE * fp); +BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], tmp[128], buf[128]; + unsigned long start_pc, end_pc, temp; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_START, buf); + SetDlgItemText(hDlg, IDC_DUMP_END, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAME, "EEdisasm.txt"); + + sprintf(buf, "%08X", psxRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, "IOPdisasm.txt"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMP_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAME, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"EE DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + + + opcode_addr=temp; + MakeDebugOpcode(); + OpcodePrintTable[(cpuRegs.code) >> 26](tmp); + if (HasBreakpoint(temp)) + { + sprintf(buf, "*%08X %08X: %s", temp, cpuRegs.code, tmp); + } + else + { + sprintf(buf, "%08X %08X: %s", temp, cpuRegs.code, tmp); + } + + fprintf(fp, "%s\n", buf); + } + + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"EE REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + EEDumpRegs(fp); + fclose(fp); + } + + + + GetDlgItemText(hDlg, IDC_DUMP_STARTIOP, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_ENDIOP, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"IOP DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + opcode_addr=temp; + MakeIOPDebugOpcode(); + IOP_DEBUG_BSC[(psxRegs.code) >> 26](tmp); + sprintf(buf, "%08X %08X: %s", temp, psxRegs.code, tmp); + fprintf(fp, "%s\n", buf); + } + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"IOP REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + IOPDumpRegs(fp); + fclose(fp); + } + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpexecProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[0].value); + SetDlgItemText(hDlg, IDC_EXECBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_EXECBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[0].value); + bkpt_regv[0].type = 1; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpcntProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[1].value); + SetDlgItemText(hDlg, IDC_CNTBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_CNTBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[1].value); + bkpt_regv[1].type = 2; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} +HINSTANCE m2_hInst; +HWND m2_hWnd; +HWND hIopDlg; + +LRESULT CALLBACK IOP_DISASM(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + hWnd_IOP_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM_IOP); + hWnd_IOP_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL_IOP); + + SendMessage(hWnd_IOP_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_IOP_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_IOP_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + RefreshIOPDebugger(); + return (TRUE); + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerIOPPC += 0x00000004; RefreshIOPDebugger(); break; + case SB_LINEUP: DebuggerIOPPC -= 0x00000004; RefreshIOPDebugger(); break; + case SB_PAGEDOWN: DebuggerIOPPC += 0x00000029; RefreshIOPDebugger(); break; + case SB_PAGEUP: DebuggerIOPPC -= 0x00000029; RefreshIOPDebugger(); break; + } + return TRUE; + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +int CreatePropertySheet2(HWND hwndOwner) +{ + PROPSHEETPAGE psp[1]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m2_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_IOP_DEBUG); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)IOP_DISASM; + psp[0].pszTitle = "Iop Disasm"; + psp[0].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m2_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "IOP Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); +} + +BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + FARPROC jmpproc, dumpproc; + FARPROC bpexecproc, bpcntproc; + u32 oldpc = 0; + + switch (message) + { + case WM_INITDIALOG: + // if (OpenPlugins() == -1) return TRUE;//moved to WinMain.c + + ShowCursor(TRUE); + + SetWindowText(hDlg, "R5900 Debugger"); + debughWnd=hDlg; + DebuggerPC = 0; + // Clear all breakpoints. + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + + hWnd_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM); + hWnd_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL); + + SendMessage(hWnd_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + hRegDlg = (HWND)CreatePropertySheet(hDlg); + hIopDlg = (HWND)CreatePropertySheet2(hDlg); + UpdateRegs(); + SetWindowPos(hRegDlg, NULL, 425, 0, 600, 515,0 ); + SetWindowPos(hIopDlg, NULL, 0 ,515,600,230,0); + RefreshDebugger(); + + + + RefreshIOPDebugger(); + return TRUE; + + case WM_VSCROLL: + + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerPC += 0x00000004; RefreshDebugAll(); break; + case SB_LINEUP: DebuggerPC -= 0x00000004; RefreshDebugAll(); break; + case SB_PAGEDOWN: DebuggerPC += 0x00000074; RefreshDebugAll(); break; + case SB_PAGEUP: DebuggerPC -= 0x00000074; RefreshDebugAll(); break; + } + + + + + return TRUE; + + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_DEBUG_STEP: + oldpc = psxRegs.pc; + Cpu->Step(); + while(oldpc == psxRegs.pc) Cpu->Step(); + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_SKIP: + cpuRegs.pc+= 4; + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_GO: + for (;;) { + if (HasBreakpoint()) { + Cpu->Step(); + break; + } + Cpu->Step(); + } + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_LOG: +#ifdef PCSX2_DEVBUILD + Log = 1 - Log; +#endif + return TRUE; + + case IDC_DEBUG_RESETTOPC: + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_JUMP: + jmpproc = MakeProcInstance((FARPROC)JumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_JUMP), debughWnd, (DLGPROC)jmpproc); + FreeProcInstance(jmpproc); + + RefreshDebugAll(); + return TRUE; + case IDC_CPUOP: + + UpdateR5900op(); + return TRUE; + + case IDC_DEBUG_BP_EXEC: + bpexecproc = MakeProcInstance((FARPROC)BpexecProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPEXEC), debughWnd, (DLGPROC)bpexecproc); + FreeProcInstance(bpexecproc); + + return TRUE; + + case IDC_DEBUG_BP_COUNT: + bpcntproc = MakeProcInstance((FARPROC)BpcntProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPCNT), debughWnd, (DLGPROC)bpcntproc); + FreeProcInstance(bpcntproc); + return TRUE; + + case IDC_DEBUG_BP_CLEAR: + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + return TRUE; + + case IDC_DEBUG_DUMP: + dumpproc = MakeProcInstance((FARPROC)DumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMP), debughWnd, (DLGPROC)dumpproc); + FreeProcInstance(dumpproc); + return TRUE; + + case IDC_DEBUG_MEMORY: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MEMORY), debughWnd, (DLGPROC)MemoryProc); + return TRUE; + + case IDC_DEBUG_CLOSE: + + EndDialog(hRegDlg ,TRUE); + EndDialog(hDlg,TRUE); + EndDialog(hIopDlg,TRUE); + + ClosePlugins(); + + return TRUE; + } + break; + } + + return FALSE; +} + +void RefreshDebugger(void) +{ + unsigned long t; + int cnt; + + + + if (DebuggerPC == 0) + DebuggerPC = cpuRegs.pc; //- 0x00000038; + + SendMessage(hWnd_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerPC, cnt = 0; t < (DebuggerPC + 0x00000074); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 *mem = (u32*)PSM(t); + char *str; + if (mem == NULL) { + char nullAddr[256]; + sprintf(nullAddr, "%8.8lx 00000000: NULL MEMORY", t); str = nullAddr; + } else { + str = disR5900Fasm(*mem, t); + } + SendMessage(hWnd_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} + +void RefreshIOPDebugger(void) +{ + unsigned long t; + int cnt; + + DebuggerIOPPC = psxRegs.pc; //- 0x00000038; + + SendMessage(hWnd_IOP_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerIOPPC, cnt = 0; t < (DebuggerIOPPC + 0x00000029); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 mem = PSXMu32(t); + char *str = disR3000Fasm(mem, t); + SendMessage(hWnd_IOP_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} diff --git a/windows/Debugger.h b/windows/Debugger.h new file mode 100644 index 0000000000..d4e3d20b47 --- /dev/null +++ b/windows/Debugger.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define NUM_BREAKPOINTS 8 + +extern void (*OpcodePrintTable[64])(char *buf); + +extern BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + + +extern BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern void RefreshDebugger(void); + +unsigned long opcode_addr; + +typedef struct +{ + int type; + unsigned long value; +} breakpoints; + +breakpoints bkpt_regv[NUM_BREAKPOINTS]; + + + +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +void UpdateRegs(void); +int CreatePropertySheet(HWND hwndOwner); diff --git a/windows/Debugreg.c b/windows/Debugreg.c new file mode 100644 index 0000000000..3edc32565a --- /dev/null +++ b/windows/Debugreg.c @@ -0,0 +1,1483 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 +#include +#include + +#include "resource.h" +#include "Debugger.h" +#include "Debug.h" +#include "R5900.h" +#include "R3000a.h" +#include "VUmicro.h" + +HINSTANCE m_hInst; +HWND m_hWnd; +char text1[256]; + + +/*R3000a registers handle */ +static HWND IOPGPR0Handle=NULL; +static HWND IOPGPR1Handle=NULL; +static HWND IOPGPR2Handle=NULL; +static HWND IOPGPR3Handle=NULL; +static HWND IOPGPR4Handle=NULL; +static HWND IOPGPR5Handle=NULL; +static HWND IOPGPR6Handle=NULL; +static HWND IOPGPR7Handle=NULL; +static HWND IOPGPR8Handle=NULL; +static HWND IOPGPR9Handle=NULL; +static HWND IOPGPR10Handle=NULL; +static HWND IOPGPR11Handle=NULL; +static HWND IOPGPR12Handle=NULL; +static HWND IOPGPR13Handle=NULL; +static HWND IOPGPR14Handle=NULL; +static HWND IOPGPR15Handle=NULL; +static HWND IOPGPR16Handle=NULL; +static HWND IOPGPR17Handle=NULL; +static HWND IOPGPR18Handle=NULL; +static HWND IOPGPR19Handle=NULL; +static HWND IOPGPR20Handle=NULL; +static HWND IOPGPR21Handle=NULL; +static HWND IOPGPR22Handle=NULL; +static HWND IOPGPR23Handle=NULL; +static HWND IOPGPR24Handle=NULL; +static HWND IOPGPR25Handle=NULL; +static HWND IOPGPR26Handle=NULL; +static HWND IOPGPR27Handle=NULL; +static HWND IOPGPR28Handle=NULL; +static HWND IOPGPR29Handle=NULL; +static HWND IOPGPR30Handle=NULL; +static HWND IOPGPR31Handle=NULL; +static HWND IOPGPRPCHandle=NULL; +static HWND IOPGPRHIHandle=NULL; +static HWND IOPGPRLOHandle=NULL; + +/*R5900 registers handle */ +static HWND GPR0Handle=NULL; +static HWND GPR1Handle=NULL; +static HWND GPR2Handle=NULL; +static HWND GPR3Handle=NULL; +static HWND GPR4Handle=NULL; +static HWND GPR5Handle=NULL; +static HWND GPR6Handle=NULL; +static HWND GPR7Handle=NULL; +static HWND GPR8Handle=NULL; +static HWND GPR9Handle=NULL; +static HWND GPR10Handle=NULL; +static HWND GPR11Handle=NULL; +static HWND GPR12Handle=NULL; +static HWND GPR13Handle=NULL; +static HWND GPR14Handle=NULL; +static HWND GPR15Handle=NULL; +static HWND GPR16Handle=NULL; +static HWND GPR17Handle=NULL; +static HWND GPR18Handle=NULL; +static HWND GPR19Handle=NULL; +static HWND GPR20Handle=NULL; +static HWND GPR21Handle=NULL; +static HWND GPR22Handle=NULL; +static HWND GPR23Handle=NULL; +static HWND GPR24Handle=NULL; +static HWND GPR25Handle=NULL; +static HWND GPR26Handle=NULL; +static HWND GPR27Handle=NULL; +static HWND GPR28Handle=NULL; +static HWND GPR29Handle=NULL; +static HWND GPR30Handle=NULL; +static HWND GPR31Handle=NULL; +static HWND GPRPCHandle=NULL; +static HWND GPRHIHandle=NULL; +static HWND GPRLOHandle=NULL; +/*end of r3000a registers handle */ +/*cop0 registers here */ +static HWND COP00Handle=NULL; +static HWND COP01Handle=NULL; +static HWND COP02Handle=NULL; +static HWND COP03Handle=NULL; +static HWND COP04Handle=NULL; +static HWND COP05Handle=NULL; +static HWND COP06Handle=NULL; +static HWND COP07Handle=NULL; +static HWND COP08Handle=NULL; +static HWND COP09Handle=NULL; +static HWND COP010Handle=NULL; +static HWND COP011Handle=NULL; +static HWND COP012Handle=NULL; +static HWND COP013Handle=NULL; +static HWND COP014Handle=NULL; +static HWND COP015Handle=NULL; +static HWND COP016Handle=NULL; +static HWND COP017Handle=NULL; +static HWND COP018Handle=NULL; +static HWND COP019Handle=NULL; +static HWND COP020Handle=NULL; +static HWND COP021Handle=NULL; +static HWND COP022Handle=NULL; +static HWND COP023Handle=NULL; +static HWND COP024Handle=NULL; +static HWND COP025Handle=NULL; +static HWND COP026Handle=NULL; +static HWND COP027Handle=NULL; +static HWND COP028Handle=NULL; +static HWND COP029Handle=NULL; +static HWND COP030Handle=NULL; +static HWND COP031Handle=NULL; +static HWND COP0PCHandle=NULL; +static HWND COP0HIHandle=NULL; +static HWND COP0LOHandle=NULL; +/*end of cop0 registers */ +/*cop1 registers here */ +static HWND COP10Handle=NULL; +static HWND COP11Handle=NULL; +static HWND COP12Handle=NULL; +static HWND COP13Handle=NULL; +static HWND COP14Handle=NULL; +static HWND COP15Handle=NULL; +static HWND COP16Handle=NULL; +static HWND COP17Handle=NULL; +static HWND COP18Handle=NULL; +static HWND COP19Handle=NULL; +static HWND COP110Handle=NULL; +static HWND COP111Handle=NULL; +static HWND COP112Handle=NULL; +static HWND COP113Handle=NULL; +static HWND COP114Handle=NULL; +static HWND COP115Handle=NULL; +static HWND COP116Handle=NULL; +static HWND COP117Handle=NULL; +static HWND COP118Handle=NULL; +static HWND COP119Handle=NULL; +static HWND COP120Handle=NULL; +static HWND COP121Handle=NULL; +static HWND COP122Handle=NULL; +static HWND COP123Handle=NULL; +static HWND COP124Handle=NULL; +static HWND COP125Handle=NULL; +static HWND COP126Handle=NULL; +static HWND COP127Handle=NULL; +static HWND COP128Handle=NULL; +static HWND COP129Handle=NULL; +static HWND COP130Handle=NULL; +static HWND COP131Handle=NULL; +static HWND COP1C0Handle=NULL; +static HWND COP1C1Handle=NULL; +static HWND COP1ACCHandle=NULL; +/*end of cop1 registers */ +/*cop2 floating registers*/ +static HWND VU0F00Handle=NULL; +static HWND VU0F01Handle=NULL; +static HWND VU0F02Handle=NULL; +static HWND VU0F03Handle=NULL; +static HWND VU0F04Handle=NULL; +static HWND VU0F05Handle=NULL; +static HWND VU0F06Handle=NULL; +static HWND VU0F07Handle=NULL; +static HWND VU0F08Handle=NULL; +static HWND VU0F09Handle=NULL; +static HWND VU0F10Handle=NULL; +static HWND VU0F11Handle=NULL; +static HWND VU0F12Handle=NULL; +static HWND VU0F13Handle=NULL; +static HWND VU0F14Handle=NULL; +static HWND VU0F15Handle=NULL; +static HWND VU0F16Handle=NULL; +static HWND VU0F17Handle=NULL; +static HWND VU0F18Handle=NULL; +static HWND VU0F19Handle=NULL; +static HWND VU0F20Handle=NULL; +static HWND VU0F21Handle=NULL; +static HWND VU0F22Handle=NULL; +static HWND VU0F23Handle=NULL; +static HWND VU0F24Handle=NULL; +static HWND VU0F25Handle=NULL; +static HWND VU0F26Handle=NULL; +static HWND VU0F27Handle=NULL; +static HWND VU0F28Handle=NULL; +static HWND VU0F29Handle=NULL; +static HWND VU0F30Handle=NULL; +static HWND VU0F31Handle=NULL; +/*end of cop2 floating registers*/ +/*cop2 control registers */ +static HWND VU0C00Handle=NULL; +static HWND VU0C01Handle=NULL; +static HWND VU0C02Handle=NULL; +static HWND VU0C03Handle=NULL; +static HWND VU0C04Handle=NULL; +static HWND VU0C05Handle=NULL; +static HWND VU0C06Handle=NULL; +static HWND VU0C07Handle=NULL; +static HWND VU0C08Handle=NULL; +static HWND VU0C09Handle=NULL; +static HWND VU0C10Handle=NULL; +static HWND VU0C11Handle=NULL; +static HWND VU0C12Handle=NULL; +static HWND VU0C13Handle=NULL; +static HWND VU0C14Handle=NULL; +static HWND VU0C15Handle=NULL; +static HWND VU0C16Handle=NULL; +static HWND VU0C17Handle=NULL; +static HWND VU0C18Handle=NULL; +static HWND VU0C19Handle=NULL; +static HWND VU0C20Handle=NULL; +static HWND VU0C21Handle=NULL; +static HWND VU0C22Handle=NULL; +static HWND VU0C23Handle=NULL; +static HWND VU0C24Handle=NULL; +static HWND VU0C25Handle=NULL; +static HWND VU0C26Handle=NULL; +static HWND VU0C27Handle=NULL; +static HWND VU0C28Handle=NULL; +static HWND VU0C29Handle=NULL; +static HWND VU0C30Handle=NULL; +static HWND VU0C31Handle=NULL; +static HWND VU0ACCHandle=NULL; +/*end of cop2 control registers */ +/*vu1 floating registers*/ +static HWND VU1F00Handle=NULL; +static HWND VU1F01Handle=NULL; +static HWND VU1F02Handle=NULL; +static HWND VU1F03Handle=NULL; +static HWND VU1F04Handle=NULL; +static HWND VU1F05Handle=NULL; +static HWND VU1F06Handle=NULL; +static HWND VU1F07Handle=NULL; +static HWND VU1F08Handle=NULL; +static HWND VU1F09Handle=NULL; +static HWND VU1F10Handle=NULL; +static HWND VU1F11Handle=NULL; +static HWND VU1F12Handle=NULL; +static HWND VU1F13Handle=NULL; +static HWND VU1F14Handle=NULL; +static HWND VU1F15Handle=NULL; +static HWND VU1F16Handle=NULL; +static HWND VU1F17Handle=NULL; +static HWND VU1F18Handle=NULL; +static HWND VU1F19Handle=NULL; +static HWND VU1F20Handle=NULL; +static HWND VU1F21Handle=NULL; +static HWND VU1F22Handle=NULL; +static HWND VU1F23Handle=NULL; +static HWND VU1F24Handle=NULL; +static HWND VU1F25Handle=NULL; +static HWND VU1F26Handle=NULL; +static HWND VU1F27Handle=NULL; +static HWND VU1F28Handle=NULL; +static HWND VU1F29Handle=NULL; +static HWND VU1F30Handle=NULL; +static HWND VU1F31Handle=NULL; +/*end of vu1 floating registers*/ +/*vu1 control registers */ +static HWND VU1C00Handle=NULL; +static HWND VU1C01Handle=NULL; +static HWND VU1C02Handle=NULL; +static HWND VU1C03Handle=NULL; +static HWND VU1C04Handle=NULL; +static HWND VU1C05Handle=NULL; +static HWND VU1C06Handle=NULL; +static HWND VU1C07Handle=NULL; +static HWND VU1C08Handle=NULL; +static HWND VU1C09Handle=NULL; +static HWND VU1C10Handle=NULL; +static HWND VU1C11Handle=NULL; +static HWND VU1C12Handle=NULL; +static HWND VU1C13Handle=NULL; +static HWND VU1C14Handle=NULL; +static HWND VU1C15Handle=NULL; +static HWND VU1C16Handle=NULL; +static HWND VU1C17Handle=NULL; +static HWND VU1C18Handle=NULL; +static HWND VU1C19Handle=NULL; +static HWND VU1C20Handle=NULL; +static HWND VU1C21Handle=NULL; +static HWND VU1C22Handle=NULL; +static HWND VU1C23Handle=NULL; +static HWND VU1C24Handle=NULL; +static HWND VU1C25Handle=NULL; +static HWND VU1C26Handle=NULL; +static HWND VU1C27Handle=NULL; +static HWND VU1C28Handle=NULL; +static HWND VU1C29Handle=NULL; +static HWND VU1C30Handle=NULL; +static HWND VU1C31Handle=NULL; +static HWND VU1ACCHandle=NULL; +/*end of vu1 control registers */ + +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +//comctl32 lib must add to project.. +int CreatePropertySheet(HWND hwndOwner) +{ + + PROPSHEETPAGE psp[7]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_GPREGS); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)R5900reg; + psp[0].pszTitle = "R5900"; + psp[0].lParam = 0; + + psp[1].dwSize = sizeof(PROPSHEETPAGE); + psp[1].dwFlags = PSP_USETITLE; + psp[1].hInstance = m_hInst; + psp[1].pszTemplate = MAKEINTRESOURCE( IDD_CP0REGS ); + psp[1].pszIcon = NULL; + psp[1].pfnDlgProc =(DLGPROC)COP0reg; + psp[1].pszTitle = "COP0"; + psp[1].lParam = 0; + + psp[2].dwSize = sizeof(PROPSHEETPAGE); + psp[2].dwFlags = PSP_USETITLE; + psp[2].hInstance = m_hInst; + psp[2].pszTemplate = MAKEINTRESOURCE( IDD_CP1REGS ); + psp[2].pszIcon = NULL; + psp[2].pfnDlgProc =(DLGPROC)COP1reg; + psp[2].pszTitle = "COP1"; + psp[2].lParam = 0; + + psp[3].dwSize = sizeof(PROPSHEETPAGE); + psp[3].dwFlags = PSP_USETITLE; + psp[3].hInstance = m_hInst; + psp[3].pszTemplate = MAKEINTRESOURCE( IDD_VU0REGS ); + psp[3].pszIcon = NULL; + psp[3].pfnDlgProc =(DLGPROC)COP2Freg; + psp[3].pszTitle = "COP2F"; + psp[3].lParam = 0; + + psp[4].dwSize = sizeof(PROPSHEETPAGE); + psp[4].dwFlags = PSP_USETITLE; + psp[4].hInstance = m_hInst; + psp[4].pszTemplate = MAKEINTRESOURCE( IDD_VU0INTEGER ); + psp[4].pszIcon = NULL; + psp[4].pfnDlgProc =(DLGPROC)COP2Creg; + psp[4].pszTitle = "COP2C"; + psp[4].lParam = 0; + + psp[5].dwSize = sizeof(PROPSHEETPAGE); + psp[5].dwFlags = PSP_USETITLE; + psp[5].hInstance = m_hInst; + psp[5].pszTemplate = MAKEINTRESOURCE( IDD_VU1REGS ); + psp[5].pszIcon = NULL; + psp[5].pfnDlgProc =(DLGPROC)VU1Freg; + psp[5].pszTitle = "VU1F"; + psp[5].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_VU1INTEGER ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)VU1Creg; + psp[6].pszTitle = "VU1C"; + psp[6].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_IOPREGS ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)R3000reg; + psp[6].pszTitle = "R3000"; + psp[6].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); + +} +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + IOPGPR0Handle=GetDlgItem(hDlg,IDC_IOPGPR0); + IOPGPR1Handle=GetDlgItem(hDlg,IDC_IOPGPR1); + IOPGPR2Handle=GetDlgItem(hDlg,IDC_IOPGPR2); + IOPGPR3Handle=GetDlgItem(hDlg,IDC_IOPGPR3); + IOPGPR4Handle=GetDlgItem(hDlg,IDC_IOPGPR4); + IOPGPR5Handle=GetDlgItem(hDlg,IDC_IOPGPR5); + IOPGPR6Handle=GetDlgItem(hDlg,IDC_IOPGPR6); + IOPGPR7Handle=GetDlgItem(hDlg,IDC_IOPGPR7); + IOPGPR8Handle=GetDlgItem(hDlg,IDC_IOPGPR8); + IOPGPR9Handle=GetDlgItem(hDlg,IDC_IOPGPR9); + IOPGPR10Handle=GetDlgItem(hDlg,IDC_IOPGPR10); + IOPGPR11Handle=GetDlgItem(hDlg,IDC_IOPGPR11); + IOPGPR12Handle=GetDlgItem(hDlg,IDC_IOPGPR12); + IOPGPR13Handle=GetDlgItem(hDlg,IDC_IOPGPR13); + IOPGPR14Handle=GetDlgItem(hDlg,IDC_IOPGPR14); + IOPGPR15Handle=GetDlgItem(hDlg,IDC_IOPGPR15); + IOPGPR16Handle=GetDlgItem(hDlg,IDC_IOPGPR16); + IOPGPR17Handle=GetDlgItem(hDlg,IDC_IOPGPR17); + IOPGPR18Handle=GetDlgItem(hDlg,IDC_IOPGPR18); + IOPGPR19Handle=GetDlgItem(hDlg,IDC_IOPGPR19); + IOPGPR20Handle=GetDlgItem(hDlg,IDC_IOPGPR20); + IOPGPR21Handle=GetDlgItem(hDlg,IDC_IOPGPR21); + IOPGPR22Handle=GetDlgItem(hDlg,IDC_IOPGPR22); + IOPGPR23Handle=GetDlgItem(hDlg,IDC_IOPGPR23); + IOPGPR24Handle=GetDlgItem(hDlg,IDC_IOPGPR24); + IOPGPR25Handle=GetDlgItem(hDlg,IDC_IOPGPR25); + IOPGPR26Handle=GetDlgItem(hDlg,IDC_IOPGPR26); + IOPGPR27Handle=GetDlgItem(hDlg,IDC_IOPGPR27); + IOPGPR28Handle=GetDlgItem(hDlg,IDC_IOPGPR28); + IOPGPR29Handle=GetDlgItem(hDlg,IDC_IOPGPR29); + IOPGPR30Handle=GetDlgItem(hDlg,IDC_IOPGPR30); + IOPGPR31Handle=GetDlgItem(hDlg,IDC_IOPGPR31); + IOPGPRPCHandle=GetDlgItem(hDlg,IDC_IOPGPR_PC); + IOPGPRHIHandle=GetDlgItem(hDlg,IDC_IOPGPR_HI); + IOPGPRLOHandle=GetDlgItem(hDlg,IDC_IOPGPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + GPR0Handle=GetDlgItem(hDlg,IDC_GPR0); + GPR1Handle=GetDlgItem(hDlg,IDC_GPR1); + GPR2Handle=GetDlgItem(hDlg,IDC_GPR2); + GPR3Handle=GetDlgItem(hDlg,IDC_GPR3); + GPR4Handle=GetDlgItem(hDlg,IDC_GPR4); + GPR5Handle=GetDlgItem(hDlg,IDC_GPR5); + GPR6Handle=GetDlgItem(hDlg,IDC_GPR6); + GPR7Handle=GetDlgItem(hDlg,IDC_GPR7); + GPR8Handle=GetDlgItem(hDlg,IDC_GPR8); + GPR9Handle=GetDlgItem(hDlg,IDC_GPR9); + GPR10Handle=GetDlgItem(hDlg,IDC_GPR10); + GPR11Handle=GetDlgItem(hDlg,IDC_GPR11); + GPR12Handle=GetDlgItem(hDlg,IDC_GPR12); + GPR13Handle=GetDlgItem(hDlg,IDC_GPR13); + GPR14Handle=GetDlgItem(hDlg,IDC_GPR14); + GPR15Handle=GetDlgItem(hDlg,IDC_GPR15); + GPR16Handle=GetDlgItem(hDlg,IDC_GPR16); + GPR17Handle=GetDlgItem(hDlg,IDC_GPR17); + GPR18Handle=GetDlgItem(hDlg,IDC_GPR18); + GPR19Handle=GetDlgItem(hDlg,IDC_GPR19); + GPR20Handle=GetDlgItem(hDlg,IDC_GPR20); + GPR21Handle=GetDlgItem(hDlg,IDC_GPR21); + GPR22Handle=GetDlgItem(hDlg,IDC_GPR22); + GPR23Handle=GetDlgItem(hDlg,IDC_GPR23); + GPR24Handle=GetDlgItem(hDlg,IDC_GPR24); + GPR25Handle=GetDlgItem(hDlg,IDC_GPR25); + GPR26Handle=GetDlgItem(hDlg,IDC_GPR26); + GPR27Handle=GetDlgItem(hDlg,IDC_GPR27); + GPR28Handle=GetDlgItem(hDlg,IDC_GPR28); + GPR29Handle=GetDlgItem(hDlg,IDC_GPR29); + GPR30Handle=GetDlgItem(hDlg,IDC_GPR30); + GPR31Handle=GetDlgItem(hDlg,IDC_GPR31); + GPRPCHandle=GetDlgItem(hDlg,IDC_GPR_PC); + GPRHIHandle=GetDlgItem(hDlg,IDC_GPR_HI); + GPRLOHandle=GetDlgItem(hDlg,IDC_GPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP00Handle=GetDlgItem(hDlg,IDC_CP00); + COP01Handle=GetDlgItem(hDlg,IDC_CP01); + COP02Handle=GetDlgItem(hDlg,IDC_CP02); + COP03Handle=GetDlgItem(hDlg,IDC_CP03); + COP04Handle=GetDlgItem(hDlg,IDC_CP04); + COP05Handle=GetDlgItem(hDlg,IDC_CP05); + COP06Handle=GetDlgItem(hDlg,IDC_CP06); + COP07Handle=GetDlgItem(hDlg,IDC_CP07); + COP08Handle=GetDlgItem(hDlg,IDC_CP08); + COP09Handle=GetDlgItem(hDlg,IDC_CP09); + COP010Handle=GetDlgItem(hDlg,IDC_CP010); + COP011Handle=GetDlgItem(hDlg,IDC_CP011); + COP012Handle=GetDlgItem(hDlg,IDC_CP012); + COP013Handle=GetDlgItem(hDlg,IDC_CP013); + COP014Handle=GetDlgItem(hDlg,IDC_CP014); + COP015Handle=GetDlgItem(hDlg,IDC_CP015); + COP016Handle=GetDlgItem(hDlg,IDC_CP016); + COP017Handle=GetDlgItem(hDlg,IDC_CP017); + COP018Handle=GetDlgItem(hDlg,IDC_CP018); + COP019Handle=GetDlgItem(hDlg,IDC_CP019); + COP020Handle=GetDlgItem(hDlg,IDC_CP020); + COP021Handle=GetDlgItem(hDlg,IDC_CP021); + COP022Handle=GetDlgItem(hDlg,IDC_CP022); + COP023Handle=GetDlgItem(hDlg,IDC_CP023); + COP024Handle=GetDlgItem(hDlg,IDC_CP024); + COP025Handle=GetDlgItem(hDlg,IDC_CP025); + COP026Handle=GetDlgItem(hDlg,IDC_CP026); + COP027Handle=GetDlgItem(hDlg,IDC_CP027); + COP028Handle=GetDlgItem(hDlg,IDC_CP028); + COP029Handle=GetDlgItem(hDlg,IDC_CP029); + COP030Handle=GetDlgItem(hDlg,IDC_CP030); + COP031Handle=GetDlgItem(hDlg,IDC_CP031); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP10Handle=GetDlgItem(hDlg,IDC_FP0); + COP11Handle=GetDlgItem(hDlg,IDC_FP1); + COP12Handle=GetDlgItem(hDlg,IDC_FP2); + COP13Handle=GetDlgItem(hDlg,IDC_FP3); + COP14Handle=GetDlgItem(hDlg,IDC_FP4); + COP15Handle=GetDlgItem(hDlg,IDC_FP5); + COP16Handle=GetDlgItem(hDlg,IDC_FP6); + COP17Handle=GetDlgItem(hDlg,IDC_FP7); + COP18Handle=GetDlgItem(hDlg,IDC_FP8); + COP19Handle=GetDlgItem(hDlg,IDC_FP9); + COP110Handle=GetDlgItem(hDlg,IDC_FP10); + COP111Handle=GetDlgItem(hDlg,IDC_FP11); + COP112Handle=GetDlgItem(hDlg,IDC_FP12); + COP113Handle=GetDlgItem(hDlg,IDC_FP13); + COP114Handle=GetDlgItem(hDlg,IDC_FP14); + COP115Handle=GetDlgItem(hDlg,IDC_FP15); + COP116Handle=GetDlgItem(hDlg,IDC_FP16); + COP117Handle=GetDlgItem(hDlg,IDC_FP17); + COP118Handle=GetDlgItem(hDlg,IDC_FP18); + COP119Handle=GetDlgItem(hDlg,IDC_FP19); + COP120Handle=GetDlgItem(hDlg,IDC_FP20); + COP121Handle=GetDlgItem(hDlg,IDC_FP21); + COP122Handle=GetDlgItem(hDlg,IDC_FP22); + COP123Handle=GetDlgItem(hDlg,IDC_FP23); + COP124Handle=GetDlgItem(hDlg,IDC_FP24); + COP125Handle=GetDlgItem(hDlg,IDC_FP25); + COP126Handle=GetDlgItem(hDlg,IDC_FP26); + COP127Handle=GetDlgItem(hDlg,IDC_FP27); + COP128Handle=GetDlgItem(hDlg,IDC_FP28); + COP129Handle=GetDlgItem(hDlg,IDC_FP29); + COP130Handle=GetDlgItem(hDlg,IDC_FP30); + COP131Handle=GetDlgItem(hDlg,IDC_FP31); + COP1C0Handle=GetDlgItem(hDlg,IDC_FCR0); + COP1C1Handle=GetDlgItem(hDlg,IDC_FCR31); + COP1ACCHandle=GetDlgItem(hDlg,IDC_FPU_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0F00Handle=GetDlgItem(hDlg,IDC_VU0_VF00); + VU0F01Handle=GetDlgItem(hDlg,IDC_VU0_VF01); + VU0F02Handle=GetDlgItem(hDlg,IDC_VU0_VF02); + VU0F03Handle=GetDlgItem(hDlg,IDC_VU0_VF03); + VU0F04Handle=GetDlgItem(hDlg,IDC_VU0_VF04); + VU0F05Handle=GetDlgItem(hDlg,IDC_VU0_VF05); + VU0F06Handle=GetDlgItem(hDlg,IDC_VU0_VF06); + VU0F07Handle=GetDlgItem(hDlg,IDC_VU0_VF07); + VU0F08Handle=GetDlgItem(hDlg,IDC_VU0_VF08); + VU0F09Handle=GetDlgItem(hDlg,IDC_VU0_VF09); + VU0F10Handle=GetDlgItem(hDlg,IDC_VU0_VF10); + VU0F11Handle=GetDlgItem(hDlg,IDC_VU0_VF11); + VU0F12Handle=GetDlgItem(hDlg,IDC_VU0_VF12); + VU0F13Handle=GetDlgItem(hDlg,IDC_VU0_VF13); + VU0F14Handle=GetDlgItem(hDlg,IDC_VU0_VF14); + VU0F15Handle=GetDlgItem(hDlg,IDC_VU0_VF15); + VU0F16Handle=GetDlgItem(hDlg,IDC_VU0_VF16); + VU0F17Handle=GetDlgItem(hDlg,IDC_VU0_VF17); + VU0F18Handle=GetDlgItem(hDlg,IDC_VU0_VF18); + VU0F19Handle=GetDlgItem(hDlg,IDC_VU0_VF19); + VU0F20Handle=GetDlgItem(hDlg,IDC_VU0_VF20); + VU0F21Handle=GetDlgItem(hDlg,IDC_VU0_VF21); + VU0F22Handle=GetDlgItem(hDlg,IDC_VU0_VF22); + VU0F23Handle=GetDlgItem(hDlg,IDC_VU0_VF23); + VU0F24Handle=GetDlgItem(hDlg,IDC_VU0_VF24); + VU0F25Handle=GetDlgItem(hDlg,IDC_VU0_VF25); + VU0F26Handle=GetDlgItem(hDlg,IDC_VU0_VF26); + VU0F27Handle=GetDlgItem(hDlg,IDC_VU0_VF27); + VU0F28Handle=GetDlgItem(hDlg,IDC_VU0_VF28); + VU0F29Handle=GetDlgItem(hDlg,IDC_VU0_VF29); + VU0F30Handle=GetDlgItem(hDlg,IDC_VU0_VF30); + VU0F31Handle=GetDlgItem(hDlg,IDC_VU0_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0C00Handle=GetDlgItem(hDlg,IDC_VU0_VI00); + VU0C01Handle=GetDlgItem(hDlg,IDC_VU0_VI01); + VU0C02Handle=GetDlgItem(hDlg,IDC_VU0_VI02); + VU0C03Handle=GetDlgItem(hDlg,IDC_VU0_VI03); + VU0C04Handle=GetDlgItem(hDlg,IDC_VU0_VI04); + VU0C05Handle=GetDlgItem(hDlg,IDC_VU0_VI05); + VU0C06Handle=GetDlgItem(hDlg,IDC_VU0_VI06); + VU0C07Handle=GetDlgItem(hDlg,IDC_VU0_VI07); + VU0C08Handle=GetDlgItem(hDlg,IDC_VU0_VI08); + VU0C09Handle=GetDlgItem(hDlg,IDC_VU0_VI09); + VU0C10Handle=GetDlgItem(hDlg,IDC_VU0_VI10); + VU0C11Handle=GetDlgItem(hDlg,IDC_VU0_VI11); + VU0C12Handle=GetDlgItem(hDlg,IDC_VU0_VI12); + VU0C13Handle=GetDlgItem(hDlg,IDC_VU0_VI13); + VU0C14Handle=GetDlgItem(hDlg,IDC_VU0_VI14); + VU0C15Handle=GetDlgItem(hDlg,IDC_VU0_VI15); + VU0C16Handle=GetDlgItem(hDlg,IDC_VU0_VI16); + VU0C17Handle=GetDlgItem(hDlg,IDC_VU0_VI17); + VU0C18Handle=GetDlgItem(hDlg,IDC_VU0_VI18); + VU0C19Handle=GetDlgItem(hDlg,IDC_VU0_VI19); + VU0C20Handle=GetDlgItem(hDlg,IDC_VU0_VI20); + VU0C21Handle=GetDlgItem(hDlg,IDC_VU0_VI21); + VU0C22Handle=GetDlgItem(hDlg,IDC_VU0_VI22); + VU0C23Handle=GetDlgItem(hDlg,IDC_VU0_VI23); + VU0C24Handle=GetDlgItem(hDlg,IDC_VU0_VI24); + VU0C25Handle=GetDlgItem(hDlg,IDC_VU0_VI25); + VU0C26Handle=GetDlgItem(hDlg,IDC_VU0_VI26); + VU0C27Handle=GetDlgItem(hDlg,IDC_VU0_VI27); + VU0C28Handle=GetDlgItem(hDlg,IDC_VU0_VI28); + VU0C29Handle=GetDlgItem(hDlg,IDC_VU0_VI29); + VU0C30Handle=GetDlgItem(hDlg,IDC_VU0_VI30); + VU0C31Handle=GetDlgItem(hDlg,IDC_VU0_VI31); + VU0ACCHandle=GetDlgItem(hDlg,IDC_VU0_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + + +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1F00Handle=GetDlgItem(hDlg,IDC_VU1_VF00); + VU1F01Handle=GetDlgItem(hDlg,IDC_VU1_VF01); + VU1F02Handle=GetDlgItem(hDlg,IDC_VU1_VF02); + VU1F03Handle=GetDlgItem(hDlg,IDC_VU1_VF03); + VU1F04Handle=GetDlgItem(hDlg,IDC_VU1_VF04); + VU1F05Handle=GetDlgItem(hDlg,IDC_VU1_VF05); + VU1F06Handle=GetDlgItem(hDlg,IDC_VU1_VF06); + VU1F07Handle=GetDlgItem(hDlg,IDC_VU1_VF07); + VU1F08Handle=GetDlgItem(hDlg,IDC_VU1_VF08); + VU1F09Handle=GetDlgItem(hDlg,IDC_VU1_VF09); + VU1F10Handle=GetDlgItem(hDlg,IDC_VU1_VF10); + VU1F11Handle=GetDlgItem(hDlg,IDC_VU1_VF11); + VU1F12Handle=GetDlgItem(hDlg,IDC_VU1_VF12); + VU1F13Handle=GetDlgItem(hDlg,IDC_VU1_VF13); + VU1F14Handle=GetDlgItem(hDlg,IDC_VU1_VF14); + VU1F15Handle=GetDlgItem(hDlg,IDC_VU1_VF15); + VU1F16Handle=GetDlgItem(hDlg,IDC_VU1_VF16); + VU1F17Handle=GetDlgItem(hDlg,IDC_VU1_VF17); + VU1F18Handle=GetDlgItem(hDlg,IDC_VU1_VF18); + VU1F19Handle=GetDlgItem(hDlg,IDC_VU1_VF19); + VU1F20Handle=GetDlgItem(hDlg,IDC_VU1_VF20); + VU1F21Handle=GetDlgItem(hDlg,IDC_VU1_VF21); + VU1F22Handle=GetDlgItem(hDlg,IDC_VU1_VF22); + VU1F23Handle=GetDlgItem(hDlg,IDC_VU1_VF23); + VU1F24Handle=GetDlgItem(hDlg,IDC_VU1_VF24); + VU1F25Handle=GetDlgItem(hDlg,IDC_VU1_VF25); + VU1F26Handle=GetDlgItem(hDlg,IDC_VU1_VF26); + VU1F27Handle=GetDlgItem(hDlg,IDC_VU1_VF27); + VU1F28Handle=GetDlgItem(hDlg,IDC_VU1_VF28); + VU1F29Handle=GetDlgItem(hDlg,IDC_VU1_VF29); + VU1F30Handle=GetDlgItem(hDlg,IDC_VU1_VF30); + VU1F31Handle=GetDlgItem(hDlg,IDC_VU1_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1C00Handle=GetDlgItem(hDlg,IDC_VU1_VI00); + VU1C01Handle=GetDlgItem(hDlg,IDC_VU1_VI01); + VU1C02Handle=GetDlgItem(hDlg,IDC_VU1_VI02); + VU1C03Handle=GetDlgItem(hDlg,IDC_VU1_VI03); + VU1C04Handle=GetDlgItem(hDlg,IDC_VU1_VI04); + VU1C05Handle=GetDlgItem(hDlg,IDC_VU1_VI05); + VU1C06Handle=GetDlgItem(hDlg,IDC_VU1_VI06); + VU1C07Handle=GetDlgItem(hDlg,IDC_VU1_VI07); + VU1C08Handle=GetDlgItem(hDlg,IDC_VU1_VI08); + VU1C09Handle=GetDlgItem(hDlg,IDC_VU1_VI09); + VU1C10Handle=GetDlgItem(hDlg,IDC_VU1_VI10); + VU1C11Handle=GetDlgItem(hDlg,IDC_VU1_VI11); + VU1C12Handle=GetDlgItem(hDlg,IDC_VU1_VI12); + VU1C13Handle=GetDlgItem(hDlg,IDC_VU1_VI13); + VU1C14Handle=GetDlgItem(hDlg,IDC_VU1_VI14); + VU1C15Handle=GetDlgItem(hDlg,IDC_VU1_VI15); + VU1C16Handle=GetDlgItem(hDlg,IDC_VU1_VI16); + VU1C17Handle=GetDlgItem(hDlg,IDC_VU1_VI17); + VU1C18Handle=GetDlgItem(hDlg,IDC_VU1_VI18); + VU1C19Handle=GetDlgItem(hDlg,IDC_VU1_VI19); + VU1C20Handle=GetDlgItem(hDlg,IDC_VU1_VI20); + VU1C21Handle=GetDlgItem(hDlg,IDC_VU1_VI21); + VU1C22Handle=GetDlgItem(hDlg,IDC_VU1_VI22); + VU1C23Handle=GetDlgItem(hDlg,IDC_VU1_VI23); + VU1C24Handle=GetDlgItem(hDlg,IDC_VU1_VI24); + VU1C25Handle=GetDlgItem(hDlg,IDC_VU1_VI25); + VU1C26Handle=GetDlgItem(hDlg,IDC_VU1_VI26); + VU1C27Handle=GetDlgItem(hDlg,IDC_VU1_VI27); + VU1C28Handle=GetDlgItem(hDlg,IDC_VU1_VI28); + VU1C29Handle=GetDlgItem(hDlg,IDC_VU1_VI29); + VU1C30Handle=GetDlgItem(hDlg,IDC_VU1_VI30); + VU1C31Handle=GetDlgItem(hDlg,IDC_VU1_VI31); + VU1ACCHandle=GetDlgItem(hDlg,IDC_VU1_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +void UpdateRegs(void) +{ + + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[0]); + SendMessage(IOPGPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[1]); + SendMessage(IOPGPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[2]); + SendMessage(IOPGPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[3]); + SendMessage(IOPGPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[4]); + SendMessage(IOPGPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[5]); + SendMessage(IOPGPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[6]); + SendMessage(IOPGPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[7]); + SendMessage(IOPGPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[8]); + SendMessage(IOPGPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[9]); + SendMessage(IOPGPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[10]); + SendMessage(IOPGPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[11]); + SendMessage(IOPGPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[12]); + SendMessage(IOPGPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[13]); + SendMessage(IOPGPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[14]); + SendMessage(IOPGPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[15]); + SendMessage(IOPGPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[16]); + SendMessage(IOPGPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[17]); + SendMessage(IOPGPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[18]); + SendMessage(IOPGPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[19]); + SendMessage(IOPGPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[20]); + SendMessage(IOPGPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[21]); + SendMessage(IOPGPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[22]); + SendMessage(IOPGPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[23]); + SendMessage(IOPGPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[24]); + SendMessage(IOPGPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[25]); + SendMessage(IOPGPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[26]); + SendMessage(IOPGPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[27]); + SendMessage(IOPGPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[28]); + SendMessage(IOPGPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[29]); + SendMessage(IOPGPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[30]); + SendMessage(IOPGPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[31]); + SendMessage(IOPGPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",psxRegs.pc ); + SendMessage(IOPGPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[32]); + SendMessage(IOPGPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[33]); + SendMessage(IOPGPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[0].UL[3],cpuRegs.GPR.r[0].UL[2],cpuRegs.GPR.r[0].UL[1],cpuRegs.GPR.r[0].UL[0] ); + SendMessage(GPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[1].UL[3], cpuRegs.GPR.r[1].UL[2],cpuRegs.GPR.r[1].UL[1],cpuRegs.GPR.r[1].UL[0] ); + SendMessage(GPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[2].UL[3],cpuRegs.GPR.r[2].UL[2], cpuRegs.GPR.r[2].UL[1],cpuRegs.GPR.r[2].UL[0]); + SendMessage(GPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[3].UL[3],cpuRegs.GPR.r[3].UL[2], cpuRegs.GPR.r[3].UL[1],cpuRegs.GPR.r[3].UL[0] ); + SendMessage(GPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[4].UL[3],cpuRegs.GPR.r[4].UL[2], cpuRegs.GPR.r[4].UL[1],cpuRegs.GPR.r[4].UL[0] ); + SendMessage(GPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[5].UL[3],cpuRegs.GPR.r[5].UL[2],cpuRegs.GPR.r[5].UL[1], cpuRegs.GPR.r[5].UL[0] ); + SendMessage(GPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[6].UL[3],cpuRegs.GPR.r[6].UL[2], cpuRegs.GPR.r[6].UL[1], cpuRegs.GPR.r[6].UL[0]); + SendMessage(GPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[7].UL[3], cpuRegs.GPR.r[7].UL[2],cpuRegs.GPR.r[7].UL[1],cpuRegs.GPR.r[7].UL[0] ); + SendMessage(GPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[8].UL[3],cpuRegs.GPR.r[8].UL[2],cpuRegs.GPR.r[8].UL[1],cpuRegs.GPR.r[8].UL[0] ); + SendMessage(GPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[9].UL[3],cpuRegs.GPR.r[9].UL[2],cpuRegs.GPR.r[9].UL[1], cpuRegs.GPR.r[9].UL[0] ); + SendMessage(GPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[10].UL[3],cpuRegs.GPR.r[10].UL[2],cpuRegs.GPR.r[10].UL[1],cpuRegs.GPR.r[10].UL[0] ); + SendMessage(GPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[11].UL[3],cpuRegs.GPR.r[11].UL[2],cpuRegs.GPR.r[11].UL[1],cpuRegs.GPR.r[11].UL[0] ); + SendMessage(GPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[12].UL[3],cpuRegs.GPR.r[12].UL[2],cpuRegs.GPR.r[12].UL[1],cpuRegs.GPR.r[12].UL[0] ); + SendMessage(GPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[13].UL[3],cpuRegs.GPR.r[13].UL[2],cpuRegs.GPR.r[13].UL[1],cpuRegs.GPR.r[13].UL[0] ); + SendMessage(GPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[14].UL[3],cpuRegs.GPR.r[14].UL[2],cpuRegs.GPR.r[14].UL[1],cpuRegs.GPR.r[14].UL[0] ); + SendMessage(GPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[15].UL[3],cpuRegs.GPR.r[15].UL[2],cpuRegs.GPR.r[15].UL[1],cpuRegs.GPR.r[15].UL[0] ); + SendMessage(GPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[16].UL[3],cpuRegs.GPR.r[16].UL[2],cpuRegs.GPR.r[16].UL[1],cpuRegs.GPR.r[16].UL[0] ); + SendMessage(GPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[17].UL[3],cpuRegs.GPR.r[17].UL[2],cpuRegs.GPR.r[17].UL[1],cpuRegs.GPR.r[17].UL[0] ); + SendMessage(GPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[18].UL[3],cpuRegs.GPR.r[18].UL[2],cpuRegs.GPR.r[18].UL[1],cpuRegs.GPR.r[18].UL[0] ); + SendMessage(GPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[19].UL[3],cpuRegs.GPR.r[19].UL[2],cpuRegs.GPR.r[19].UL[1],cpuRegs.GPR.r[19].UL[0] ); + SendMessage(GPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[20].UL[3],cpuRegs.GPR.r[20].UL[2],cpuRegs.GPR.r[20].UL[1],cpuRegs.GPR.r[20].UL[0] ); + SendMessage(GPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[21].UL[3],cpuRegs.GPR.r[21].UL[2],cpuRegs.GPR.r[21].UL[1],cpuRegs.GPR.r[21].UL[0] ); + SendMessage(GPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[22].UL[3],cpuRegs.GPR.r[22].UL[2],cpuRegs.GPR.r[22].UL[1],cpuRegs.GPR.r[22].UL[0] ); + SendMessage(GPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[23].UL[3],cpuRegs.GPR.r[23].UL[2],cpuRegs.GPR.r[23].UL[1],cpuRegs.GPR.r[23].UL[0] ); + SendMessage(GPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[24].UL[3],cpuRegs.GPR.r[24].UL[2],cpuRegs.GPR.r[24].UL[1],cpuRegs.GPR.r[24].UL[0] ); + SendMessage(GPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[25].UL[3],cpuRegs.GPR.r[25].UL[2],cpuRegs.GPR.r[25].UL[1],cpuRegs.GPR.r[25].UL[0] ); + SendMessage(GPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[26].UL[3],cpuRegs.GPR.r[26].UL[2],cpuRegs.GPR.r[26].UL[1],cpuRegs.GPR.r[26].UL[0] ); + SendMessage(GPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[27].UL[3],cpuRegs.GPR.r[27].UL[2],cpuRegs.GPR.r[27].UL[1],cpuRegs.GPR.r[27].UL[0] ); + SendMessage(GPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[28].UL[3],cpuRegs.GPR.r[28].UL[2],cpuRegs.GPR.r[28].UL[1],cpuRegs.GPR.r[28].UL[0] ); + SendMessage(GPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[29].UL[3],cpuRegs.GPR.r[29].UL[2],cpuRegs.GPR.r[29].UL[1],cpuRegs.GPR.r[29].UL[0] ); + SendMessage(GPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[30].UL[3],cpuRegs.GPR.r[30].UL[2],cpuRegs.GPR.r[30].UL[1],cpuRegs.GPR.r[30].UL[0] ); + SendMessage(GPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[31].UL[3],cpuRegs.GPR.r[31].UL[2],cpuRegs.GPR.r[31].UL[1],cpuRegs.GPR.r[31].UL[0] ); + SendMessage(GPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.pc ); + SendMessage(GPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2] ,cpuRegs.HI.UL[1] ,cpuRegs.HI.UL[0] ); + SendMessage(GPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0\0",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0] ); + SendMessage(GPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[0] ); + SendMessage(COP00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[1]); + SendMessage(COP01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[2]); + SendMessage(COP02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[3]); + SendMessage(COP03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[4]); + SendMessage(COP04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[5]); + SendMessage(COP05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[6]); + SendMessage(COP06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[7]); + SendMessage(COP07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[8]); + SendMessage(COP08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[9]); + SendMessage(COP09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[10]); + SendMessage(COP010Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[11]); + SendMessage(COP011Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[12]); + SendMessage(COP012Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[13]); + SendMessage(COP013Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[14]); + SendMessage(COP014Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[15]); + SendMessage(COP015Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[16]); + SendMessage(COP016Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[17]); + SendMessage(COP017Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[18]); + SendMessage(COP018Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[19]); + SendMessage(COP019Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[20]); + SendMessage(COP020Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[21]); + SendMessage(COP021Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[22]); + SendMessage(COP022Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[23]); + SendMessage(COP023Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[24]); + SendMessage(COP024Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[25]); + SendMessage(COP025Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[26]); + SendMessage(COP026Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[27]); + SendMessage(COP027Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[28]); + SendMessage(COP028Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[29]); + SendMessage(COP029Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[30]); + SendMessage(COP030Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[31]); + SendMessage(COP031Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f",fpuRegs.fpr[0].f ); + SendMessage(COP10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[1].f); + SendMessage(COP11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[2].f); + SendMessage(COP12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[3].f); + SendMessage(COP13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[4].f); + SendMessage(COP14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[5].f); + SendMessage(COP15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[6].f); + SendMessage(COP16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[7].f); + SendMessage(COP17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[8].f); + SendMessage(COP18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[9].f); + SendMessage(COP19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[10].f); + SendMessage(COP110Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[11].f); + SendMessage(COP111Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[12].f); + SendMessage(COP112Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[13].f); + SendMessage(COP113Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[14].f); + SendMessage(COP114Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[15].f); + SendMessage(COP115Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[16].f); + SendMessage(COP116Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[17].f); + SendMessage(COP117Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[18].f); + SendMessage(COP118Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[19].f); + SendMessage(COP119Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[20].f); + SendMessage(COP120Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[21].f); + SendMessage(COP121Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[22].f); + SendMessage(COP122Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[23].f); + SendMessage(COP123Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[24].f); + SendMessage(COP124Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[25].f); + SendMessage(COP125Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[26].f); + SendMessage(COP126Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[27].f); + SendMessage(COP127Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[28].f); + SendMessage(COP128Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[29].f); + SendMessage(COP129Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[30].f); + SendMessage(COP130Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[31].f); + SendMessage(COP131Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[0]); + SendMessage(COP1C0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[31]); + SendMessage(COP1C1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.ACC.f); + SendMessage(COP1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[0].f.w,VU0.VF[0].f.z,VU0.VF[0].f.y,VU0.VF[0].f.x ); + SendMessage(VU0F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[1].f.w,VU0.VF[1].f.z,VU0.VF[1].f.y,VU0.VF[1].f.x ); + SendMessage(VU0F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[2].f.w,VU0.VF[2].f.z,VU0.VF[2].f.y,VU0.VF[2].f.x ); + SendMessage(VU0F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[3].f.w,VU0.VF[3].f.z,VU0.VF[3].f.y,VU0.VF[3].f.x ); + SendMessage(VU0F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[4].f.w,VU0.VF[4].f.z,VU0.VF[4].f.y,VU0.VF[4].f.x ); + SendMessage(VU0F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[5].f.w,VU0.VF[5].f.z,VU0.VF[5].f.y,VU0.VF[5].f.x); + SendMessage(VU0F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[6].f.w,VU0.VF[6].f.z,VU0.VF[6].f.y,VU0.VF[6].f.x ); + SendMessage(VU0F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[7].f.w,VU0.VF[7].f.z,VU0.VF[7].f.y,VU0.VF[7].f.x ); + SendMessage(VU0F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[8].f.w,VU0.VF[8].f.z,VU0.VF[8].f.y,VU0.VF[8].f.x ); + SendMessage(VU0F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[9].f.w,VU0.VF[9].f.z,VU0.VF[9].f.y,VU0.VF[9].f.x ); + SendMessage(VU0F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[10].f.w,VU0.VF[10].f.z,VU0.VF[10].f.y,VU0.VF[10].f.x ); + SendMessage(VU0F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[11].f.w,VU0.VF[11].f.z,VU0.VF[11].f.y,VU0.VF[11].f.x ); + SendMessage(VU0F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[12].f.w,VU0.VF[12].f.z,VU0.VF[12].f.y,VU0.VF[12].f.x ); + SendMessage(VU0F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[13].f.w,VU0.VF[13].f.z,VU0.VF[13].f.y,VU0.VF[13].f.x ); + SendMessage(VU0F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[14].f.w,VU0.VF[14].f.z,VU0.VF[14].f.y,VU0.VF[14].f.x ); + SendMessage(VU0F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[15].f.w,VU0.VF[15].f.z,VU0.VF[15].f.y,VU0.VF[15].f.x ); + SendMessage(VU0F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[16].f.w,VU0.VF[16].f.z,VU0.VF[16].f.y,VU0.VF[16].f.x ); + SendMessage(VU0F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[17].f.w,VU0.VF[17].f.z,VU0.VF[17].f.y,VU0.VF[17].f.x ); + SendMessage(VU0F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[18].f.w,VU0.VF[18].f.z,VU0.VF[18].f.y,VU0.VF[18].f.x ); + SendMessage(VU0F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[19].f.w,VU0.VF[19].f.z,VU0.VF[19].f.y,VU0.VF[19].f.x ); + SendMessage(VU0F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[20].f.w,VU0.VF[20].f.z,VU0.VF[20].f.y,VU0.VF[20].f.x ); + SendMessage(VU0F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[21].f.w,VU0.VF[21].f.z,VU0.VF[21].f.y,VU0.VF[21].f.x ); + SendMessage(VU0F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[22].f.w,VU0.VF[22].f.z,VU0.VF[22].f.y,VU0.VF[22].f.x ); + SendMessage(VU0F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[23].f.w,VU0.VF[23].f.z,VU0.VF[23].f.y,VU0.VF[23].f.x ); + SendMessage(VU0F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[24].f.w,VU0.VF[24].f.z,VU0.VF[24].f.y,VU0.VF[24].f.x ); + SendMessage(VU0F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[25].f.w,VU0.VF[25].f.z,VU0.VF[25].f.y,VU0.VF[25].f.x ); + SendMessage(VU0F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[26].f.w,VU0.VF[26].f.z,VU0.VF[26].f.y,VU0.VF[26].f.x ); + SendMessage(VU0F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[27].f.w,VU0.VF[27].f.z,VU0.VF[27].f.y,VU0.VF[27].f.x ); + SendMessage(VU0F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[28].f.w,VU0.VF[28].f.z,VU0.VF[28].f.y,VU0.VF[28].f.x ); + SendMessage(VU0F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[29].f.w,VU0.VF[29].f.z,VU0.VF[29].f.y,VU0.VF[29].f.x ); + SendMessage(VU0F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[30].f.w,VU0.VF[30].f.z,VU0.VF[30].f.y,VU0.VF[30].f.x ); + SendMessage(VU0F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[31].f.w,VU0.VF[31].f.z,VU0.VF[31].f.y,VU0.VF[31].f.x ); + SendMessage(VU0F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU0.VI[0] ); + SendMessage(VU0C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[1]); + SendMessage(VU0C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[2]); + SendMessage(VU0C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[3]); + SendMessage(VU0C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[4]); + SendMessage(VU0C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[5]); + SendMessage(VU0C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[6]); + SendMessage(VU0C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[7]); + SendMessage(VU0C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[8]); + SendMessage(VU0C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[9]); + SendMessage(VU0C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[10]); + SendMessage(VU0C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[11]); + SendMessage(VU0C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[12]); + SendMessage(VU0C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[13]); + SendMessage(VU0C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[14]); + SendMessage(VU0C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[15]); + SendMessage(VU0C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[16]); + SendMessage(VU0C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[17]); + SendMessage(VU0C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[18]); + SendMessage(VU0C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[19]); + SendMessage(VU0C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[20]); + SendMessage(VU0C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[21]); + SendMessage(VU0C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[22]); + SendMessage(VU0C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[23]); + SendMessage(VU0C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[24]); + SendMessage(VU0C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[25]); + SendMessage(VU0C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[26]); + SendMessage(VU0C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[27]); + SendMessage(VU0C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[28]); + SendMessage(VU0C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[29]); + SendMessage(VU0C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[30]); + SendMessage(VU0C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[31]); + SendMessage(VU0C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU0.ACC.f.w,VU0.ACC.f.z,VU0.ACC.f.y,VU0.ACC.f.x ); + SendMessage(VU0ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[0].f.w,VU1.VF[0].f.z,VU1.VF[0].f.y,VU1.VF[0].f.x ); + SendMessage(VU1F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[1].f.w,VU1.VF[1].f.z,VU1.VF[1].f.y,VU1.VF[1].f.x ); + SendMessage(VU1F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[2].f.w,VU1.VF[2].f.z,VU1.VF[2].f.y,VU1.VF[2].f.x ); + SendMessage(VU1F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[3].f.w,VU1.VF[3].f.z,VU1.VF[3].f.y,VU1.VF[3].f.x ); + SendMessage(VU1F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[4].f.w,VU1.VF[4].f.z,VU1.VF[4].f.y,VU1.VF[4].f.x ); + SendMessage(VU1F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[5].f.w,VU1.VF[5].f.z,VU1.VF[5].f.y,VU1.VF[5].f.x); + SendMessage(VU1F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[6].f.w,VU1.VF[6].f.z,VU1.VF[6].f.y,VU1.VF[6].f.x ); + SendMessage(VU1F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[7].f.w,VU1.VF[7].f.z,VU1.VF[7].f.y,VU1.VF[7].f.x ); + SendMessage(VU1F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[8].f.w,VU1.VF[8].f.z,VU1.VF[8].f.y,VU1.VF[8].f.x ); + SendMessage(VU1F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[9].f.w,VU1.VF[9].f.z,VU1.VF[9].f.y,VU1.VF[9].f.x ); + SendMessage(VU1F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[10].f.w,VU1.VF[10].f.z,VU1.VF[10].f.y,VU1.VF[10].f.x ); + SendMessage(VU1F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[11].f.w,VU1.VF[11].f.z,VU1.VF[11].f.y,VU1.VF[11].f.x ); + SendMessage(VU1F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[12].f.w,VU1.VF[12].f.z,VU1.VF[12].f.y,VU1.VF[12].f.x ); + SendMessage(VU1F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[13].f.w,VU1.VF[13].f.z,VU1.VF[13].f.y,VU1.VF[13].f.x ); + SendMessage(VU1F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[14].f.w,VU1.VF[14].f.z,VU1.VF[14].f.y,VU1.VF[14].f.x ); + SendMessage(VU1F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[15].f.w,VU1.VF[15].f.z,VU1.VF[15].f.y,VU1.VF[15].f.x ); + SendMessage(VU1F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[16].f.w,VU1.VF[16].f.z,VU1.VF[16].f.y,VU1.VF[16].f.x ); + SendMessage(VU1F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[17].f.w,VU1.VF[17].f.z,VU1.VF[17].f.y,VU1.VF[17].f.x ); + SendMessage(VU1F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[18].f.w,VU1.VF[18].f.z,VU1.VF[18].f.y,VU1.VF[18].f.x ); + SendMessage(VU1F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[19].f.w,VU1.VF[19].f.z,VU1.VF[19].f.y,VU1.VF[19].f.x ); + SendMessage(VU1F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[20].f.w,VU1.VF[20].f.z,VU1.VF[20].f.y,VU1.VF[20].f.x ); + SendMessage(VU1F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[21].f.w,VU1.VF[21].f.z,VU1.VF[21].f.y,VU1.VF[21].f.x ); + SendMessage(VU1F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[22].f.w,VU1.VF[22].f.z,VU1.VF[22].f.y,VU1.VF[22].f.x ); + SendMessage(VU1F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[23].f.w,VU1.VF[23].f.z,VU1.VF[23].f.y,VU1.VF[23].f.x ); + SendMessage(VU1F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[24].f.w,VU1.VF[24].f.z,VU1.VF[24].f.y,VU1.VF[24].f.x ); + SendMessage(VU1F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[25].f.w,VU1.VF[25].f.z,VU1.VF[25].f.y,VU1.VF[25].f.x ); + SendMessage(VU1F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[26].f.w,VU1.VF[26].f.z,VU1.VF[26].f.y,VU1.VF[26].f.x ); + SendMessage(VU1F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[27].f.w,VU1.VF[27].f.z,VU1.VF[27].f.y,VU1.VF[27].f.x ); + SendMessage(VU1F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[28].f.w,VU1.VF[28].f.z,VU1.VF[28].f.y,VU1.VF[28].f.x ); + SendMessage(VU1F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[29].f.w,VU1.VF[29].f.z,VU1.VF[29].f.y,VU1.VF[29].f.x ); + SendMessage(VU1F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[30].f.w,VU1.VF[30].f.z,VU1.VF[30].f.y,VU1.VF[30].f.x ); + SendMessage(VU1F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[31].f.w,VU1.VF[31].f.z,VU1.VF[31].f.y,VU1.VF[31].f.x ); + SendMessage(VU1F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU1.VI[0] ); + SendMessage(VU1C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[1]); + SendMessage(VU1C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[2]); + SendMessage(VU1C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[3]); + SendMessage(VU1C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[4]); + SendMessage(VU1C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[5]); + SendMessage(VU1C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[6]); + SendMessage(VU1C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[7]); + SendMessage(VU1C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[8]); + SendMessage(VU1C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[9]); + SendMessage(VU1C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[10]); + SendMessage(VU1C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[11]); + SendMessage(VU1C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[12]); + SendMessage(VU1C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[13]); + SendMessage(VU1C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[14]); + SendMessage(VU1C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[15]); + SendMessage(VU1C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[16]); + SendMessage(VU1C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[17]); + SendMessage(VU1C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[18]); + SendMessage(VU1C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[19]); + SendMessage(VU1C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[20]); + SendMessage(VU1C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[21]); + SendMessage(VU1C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[22]); + SendMessage(VU1C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[23]); + SendMessage(VU1C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[24]); + SendMessage(VU1C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[25]); + SendMessage(VU1C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[26]); + SendMessage(VU1C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[27]); + SendMessage(VU1C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[28]); + SendMessage(VU1C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[29]); + SendMessage(VU1C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[30]); + SendMessage(VU1C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[31]); + SendMessage(VU1C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU1.ACC.f.w,VU1.ACC.f.z,VU1.ACC.f.y,VU1.ACC.f.x ); + SendMessage(VU1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + +} + + +void EEDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x_%x_%x_%x",cpuRegs.GPR.r[i].UL[3],cpuRegs.GPR.r[i].UL[2],cpuRegs.GPR.r[i].UL[1],cpuRegs.GPR.r[i].UL[0]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",cpuRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2],cpuRegs.HI.UL[1],cpuRegs.HI.UL[0]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + + + for(i = 0; i < 32; i++) + { + sprintf(text1,"0x%x",cpuRegs.CP0.r[i]); + sprintf(text2,"COP0 Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } +} + +void IOPDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x",psxRegs.GPR.r[i]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",psxRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[32]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[33]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); +} diff --git a/windows/Makefile b/windows/Makefile new file mode 100644 index 0000000000..01ad78374f --- /dev/null +++ b/windows/Makefile @@ -0,0 +1,108 @@ +# +# PCSX2 Makefile for MINGW32 +# + + +all: pcsx2 + +CPU = ix86 +PCSX2 = pcsx2.exe + +CC = gcc +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +_OPTIMIZE = -fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing -m128bit-long-double +OPTIMIZE = -g -O2 ${_OPTIMIZE} +ROPTIMIZE = -O2 ${_OPTIMIZE} +RSOPTIMIZE = -O3 ${_OPTIMIZE} -mfpmath=sse -march=athlon64 +FLAGS = -D__WIN32__ -D__MINGW32__ -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -lintl -lpthreadGC +RESOBJ = pcsx2.o + +OBJS = ../Counters.o ../DebugTools/DisR5900.o ../Elfheader.o \ + ../Hw.o ../Memory.o ../Misc.o ../GS.o ../FiFo.o ../Sif.o\ + ../Plugins.o ../R5900.o ../InterTables.o ../Interpreter.o \ + ../COP0.o ../FPU.o ../VU0.o ../VU0micro.o ../VU1micro.o ../VUflags.o \ + ../MMI.o ../Vif.o ../SPR.o ../DebugTools/DisR5900asm.o ../IPU/IPU.o \ + ../DebugTools/DisVU0Micro.o ../DebugTools/DisVU1Micro.o ../CDVDiso.o ../CDVDisodrv.o \ + ../DebugTools/cpuopsDebug.o ../IPU/mpeg2lib/Idct.o ../IPU/mpeg2lib/Mpeg.o ../IPU/yuv2rgb.o \ + ../Patch.o ../Stats.o ../VUops.o \ + ../VifDma.o ../Cache.o +OBJS+= ../R3000A.o ../DebugTools/DisR3000A.o ../DebugTools/DisR3000asm.o ../PsxBios.o \ + ../PsxMem.o ../PsxInterpreter.o ../PsxCounters.o ../PsxHw.o \ + ../PsxDma.o ../Gte.o ../Sio.o ../CdRom.o ../Mdec.o \ + ../Decode_XA.o ../PsxGPU.o ../PsxSio2.o ../CDVD.o + +OBJS+= WinMain.o ini.o AboutDlg.o ConfigDlg.o McdsDlg.o PatchBrowser.o \ + DebugMemory.o Debugreg.o RDebugger.o Debugger.o CpuDlg.o ${RESOBJ} \ + ../RDebug/deci2.o ../RDebug/deci2_dbgp.o \ + ../RDebug/deci2_dcmp.o \ + ../RDebug/deci2_iloadp.o ../RDebug/deci2_netmp.o \ + ../RDebug/deci2_ttyp.o +OBJS+= ../zlib/adler32.o ../zlib/compress.o ../zlib/crc32.o ../zlib/gzio.o ../zlib/uncompr.o ../zlib/deflate.o ../zlib/trees.o \ + ../zlib/zutil.o ../zlib/inflate.o ../zlib/infback.o ../zlib/inftrees.o ../zlib/inffast.o +#../RDebug/deci2_drfp.o + +ifeq (${CPU}, ix86) + OBJS+= ../x86/iR5900.o ../ix86-32/iR5900Arit.o ../ix86-32/iR5900AritImm.o \ + ../ix86-32/iR5900Branch.o ../ix86-32/iR5900Jump.o ../ix86-32/iR5900LoadStore.o \ + ../ix86-32/iR5900Move.o ../ix86-32/iR5900MultDiv.o ../ix86-32/iR5900Shift.o \ + ../x86/recCOP2.o ../x86/iCP0.o \ + ../x86/iFPU.o ../x86/iMMI.o ../x86/iVUmicro.o \ + ../x86/iVU0micro.o ../x86/iVU1micro.o ../x86/iR3000A.o + FLAGS+= -I../ix86-32 -I../x86 + OBJS+= ../x86/ix86/ix86.o ../x86/ix86/ix86_fpu.o \ + ../x86/ix86/ix86_3dnow.o ../x86/ix86/ix86_mmx.o \ + ../x86/ix86/ix86_cpudetect.o ../x86/ix86/ix86_sse.o +endif + +DEPS:= $(OBJS:.o=.d) +ROBJS:= $(OBJS:.o=.ro) +RESROBJ:= $(RESOBJ:.o=.ro) +RSOBJS:= $(OBJS:.o=.rso) +RESRSOBJ:= $(RESOBJ:.o=.rso) + +_CFLAGS = -Wall -mwindows -I. -I.. -I../zlib -I../IPU -I../DebugTools -Imingw ${FLAGS} +CFLAGS = ${_CFLAGS} ${OPTIMIZE} +CRFLAGS = ${_CFLAGS} ${ROPTIMIZE} +CRSFLAGS = ${_CFLAGS} ${RSOPTIMIZE} + +pcsx2: ${OBJS} + ${CC} ${CFLAGS} ${OBJS} -o ${PCSX2} ${LIBS} + +release: ${ROBJS} + ${CC} ${CFLAGS} ${ROBJS} -o ${PCSX2} ${LIBS} + ${STRIP} ${PCSX2} + +release-sse: ${RSOBJS} + ${CC} ${CSSEFLAGS} ${RSOBJS} -o ${PCSX2} ${LIBS} + ${STRIP} ${PCSX2} + +.PHONY: clean pcsx2 release release-sse + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} ${ROBJS} ${RSOBJS} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.ro: %.c + ${CC} ${CRFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.rso: %.c + ${CC} ${CRSFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: pcsx2.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +${RESROBJ}: pcsx2.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +${RESRSOBJ}: pcsx2.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +-include ${DEPS} diff --git a/windows/McdsDlg.c b/windows/McdsDlg.c new file mode 100644 index 0000000000..f425919be7 --- /dev/null +++ b/windows/McdsDlg.c @@ -0,0 +1,124 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + + +HWND mcdDlg; + + +void Open_Mcd_Proc(HWND hW, int mcd) { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[1024]; + char *str; + + memset(szFileName, 0, sizeof(szFileName)); + memset(szFileTitle, 0, sizeof(szFileTitle)); + memset(szFilter, 0, sizeof(szFilter)); + + + strcpy(szFilter, _("Ps2 Memory Card (*.ps2)")); + str = szFilter + strlen(szFilter) + 1; + strcpy(str, "*.ps2"); + + str+= strlen(str) + 1; + strcpy(str, _("All Files")); + str+= strlen(str) + 1; + strcpy(str, "*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hW; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = "memcards"; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "MC2"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + Edit_SetText(GetDlgItem(hW,mcd == 1 ? IDC_MCD1 : IDC_MCD2), szFileName); + } +} + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + mcdDlg = hW; + + SetWindowText(hW, _("Memcard Manager")); + + Button_SetText(GetDlgItem(hW, IDOK), _("OK")); + Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL1), _("Select Mcd")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL2), _("Select Mcd")); + + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD1), _("Memory Card 1")); + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD2), _("Memory Card 2")); + + if (!strlen(Config.Mcd1)) strcpy(Config.Mcd1, "memcards\\Mcd001.ps2"); + if (!strlen(Config.Mcd2)) strcpy(Config.Mcd2, "memcards\\Mcd002.ps2"); + Edit_SetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1); + Edit_SetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_MCDSEL1: + Open_Mcd_Proc(hW, 1); + return TRUE; + case IDC_MCDSEL2: + Open_Mcd_Proc(hW, 2); + return TRUE; + case IDCANCEL: + EndDialog(hW,FALSE); + + return TRUE; + case IDOK: + Edit_GetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1, 256); + Edit_GetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2, 256); + + SaveConfig(); + + EndDialog(hW,TRUE); + + return TRUE; + } + case WM_DESTROY: + return TRUE; + } + return FALSE; +} + diff --git a/windows/McdsDlg.h b/windows/McdsDlg.h new file mode 100644 index 0000000000..c911430ef5 --- /dev/null +++ b/windows/McdsDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MCDSDLG_H__ +#define __MCDSDLG_H__ + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __MCDSDLG_H__ */ diff --git a/windows/PatchBrowser.c b/windows/PatchBrowser.c new file mode 100644 index 0000000000..465294abf1 --- /dev/null +++ b/windows/PatchBrowser.c @@ -0,0 +1,352 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/************************** +* +* patchbrowser.c contains all the src of patchbrowser window +* no interaction with emulation code +***************************/ + +#include +#include +#include "Common.h" +#include "win32.h" +#include "resource.h" + +/* + * TODO: + * - not topmost + * - resize stuff + * - ask to save in exit (check if changed) + */ +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + int tmpi,i; + char fileName[MAX_PATH], *tmpStr; + FILE *fp; + + switch(uMsg) { + + case WM_INITDIALOG: + SetWindowText(hW, _("Patches Browser")); + Button_SetText(GetDlgItem(hW,IDC_REFRESHPATCHLIST), _("Refresh List")); + Button_SetText(GetDlgItem(hW,IDC_NEWPATCH), _("New Patch")); + Button_SetText(GetDlgItem(hW,IDC_SAVEPATCH), _("Save Patch")); + Button_SetText(GetDlgItem(hW,IDC_EXITPB), _("Exit")); + Static_SetText(GetDlgItem(hW,IDC_GAMENAMESEARCH), _("Search game name patch:")); + //List Patches + ListPatches ((HWND) hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + + case IDC_NEWPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"a")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't create the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + fclose(fp); + i = MessageBox(hW,(LPCTSTR)"File created sucessfully.\nClear textbox?",NULL,(UINT)(MB_YESNO|MB_ICONQUESTION)); + if (i==IDYES) SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)""); + + return TRUE; + + case IDC_SAVEPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"w")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't save the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + tmpi = SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_GETLINECOUNT, (WPARAM)NULL, (LPARAM)NULL); + i=0; + for (;tmpi>=0;tmpi--) + i += SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_LINELENGTH, (WPARAM)tmpi, (LPARAM)NULL); + + tmpStr = (char *) malloc(i); + sprintf(tmpStr,""); + SendDlgItemMessage(hW, IDC_PATCHTEXT, WM_GETTEXT, (WPARAM)i, (LPARAM)tmpStr); + + //remove \r + for (i=0,tmpi=0; tmpStr[i]!='\0'; i++) + if (tmpStr[i] != '\r') + tmpStr[tmpi++] = tmpStr[i]; + tmpStr[tmpi] = '\0'; + + fputs(tmpStr,fp); + + fclose(fp); + free(tmpStr); + + MessageBox(hW,(LPCTSTR)"File saved sucessfully.",NULL,(UINT)MB_ICONINFORMATION); + + return TRUE; + + case IDC_REFRESHPATCHLIST: + + //List Patches + ListPatches ((HWND) hW); + + return TRUE; + + case IDC_EXITPB: + + //Close Dialog + EndDialog(hW, FALSE); + + return TRUE; + + case IDC_PATCHCRCLIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + return ReadPatch ((HWND) hW, fileName); + + case IDC_PATCHNAMELIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + //another small hack :p + //eg. SOCOM Demo PAL (7dd01dd9.pnach) + for (i=0;i<(int)strlen(fileName);i++) + if (fileName[i] == '(') tmpi = i; + + sprintf(fileName,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + fileName[tmpi+1],fileName[tmpi+2],fileName[tmpi+3], + fileName[tmpi+4],fileName[tmpi+5],fileName[tmpi+6], + fileName[tmpi+7],fileName[tmpi+8],fileName[tmpi+9], + fileName[tmpi+10],fileName[tmpi+11],fileName[tmpi+12], + fileName[tmpi+13],fileName[tmpi+14]); + + //sanity check + if (fileName[tmpi+15] != ')') return FALSE; + + return ReadPatch ((HWND) hW, fileName); + + case IDC_SEARCHPATCHTEXT: + + //get text + SendDlgItemMessage(hW, IDC_SEARCHPATCHTEXT, EM_GETLINE, 0, (LPARAM)fileName); + //search + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)fileName); + //select match item + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_SETCURSEL, (WPARAM)tmpi, (LPARAM)NULL); + + return TRUE; + } + return TRUE; + + case WM_CLOSE: + EndDialog(hW, FALSE); + break; + + } + return FALSE; +} +void ListPatches (HWND hW) { + + int i, tmpi, filesize, totalPatch=0, totalSize=0; + char tmpStr[MAX_PATH], *fileData; + WIN32_FIND_DATA FindData; + HANDLE Find; + FILE *fp; + + //clear listbox's + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + + //sprintf(tmpStr,"%s*.pnach", Config.PatchDir) + sprintf(tmpStr, "patches\\*.pnach"); + + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + + sprintf(tmpStr,"%s", FindData.cFileName); + + //add file name to crc list + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT) LB_ADDSTRING, (WPARAM)NULL, (LPARAM)tmpStr); + + //sprintf(tmpStr,"%s%s", Config.PatchDir, FindData.cFileName) + sprintf(tmpStr,"patches\\%s", FindData.cFileName); + + fp = fopen(tmpStr, "r"); + if (fp == NULL) break; + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + totalSize += filesize; + fseek(fp, 0, SEEK_SET); + + fileData = (char *) malloc(filesize); + sprintf(fileData,""); + + //read file + while((tmpi=fgetc(fp)) != EOF) + sprintf(fileData,"%s%c",fileData,tmpi); + + //small hack :p + for(i=0;ii;tmpi--) + fileData[tmpi] = fileData[tmpi-1]; + fileData[i] = '\r'; + fileData[i+1] = '\n'; + i++; + } + } + + SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)fileData); + + sprintf(fileData,""); + fclose(fp); + + return TRUE; +} + + +//Left Trim (remove the spaces at the left of a string) +char * lTrim (char *s) { + int count=0,i,tmpi; + + for (i=0;i<(int)strlen(s); i++) { + if (s[i] == ' ') count++; + else { + for (tmpi=0;tmpi<(int)strlen(s);tmpi++) + s[tmpi] = s[tmpi+count]; + break; + } + } + return s; +} + + +BOOL Save_Patch_Proc( char * filename ) { + + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "Patch Files (*.pnach)\0*.pnach\0ALL Files (*.*)\0*.*"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "TXT"; + ofn.Flags = OFN_EXPLORER | OFN_LONGNAMES | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; + + if ( GetSaveFileName( &ofn ) ) { + + strcpy( filename, szFileName ); + + return TRUE; + } + else { + return FALSE; + } +} diff --git a/windows/RDebugger.c b/windows/RDebugger.c new file mode 100644 index 0000000000..576cc57530 --- /dev/null +++ b/windows/RDebugger.c @@ -0,0 +1,375 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "RDebugger.h" +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "../rdebug/deci2.h" + +u32 port=8510; +SOCKET serversocket, remote; +char message[1024]; //message to add to listbox + +int runStatus=STOP, runCode=0, runCount=1; +HANDLE runEvent=NULL; + +DECI2_DBGP_BRK ebrk[32], + ibrk[32]; +int ebrk_count=0, + ibrk_count=0; + +int debuggedCpu=0; //default is to debug EE cpu; IOP=1 +u32 breakAddress=0; //disabled; ie. you cannot use address 0 for a breakpoint +u32 breakCycle=0; //disabled; ie. you cannot stop after 0 cycles + +int CreateSocket(HWND hDlg, int port){ + WSADATA wsadata; + SOCKADDR_IN saServer; + + if (WSAStartup( MAKEWORD(1, 1), &wsadata) || + ((serversocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET)){ + MessageBox(hDlg, "Could not create socket\n[Is TCP/IP installed? WinSock 1.1 or above?]", 0, MB_OK); + return FALSE; + } + sprintf(message, "[PCSX2] %s status=%s", wsadata.szDescription, wsadata.szSystemStatus); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + saServer.sin_family = AF_INET; + saServer.sin_addr.S_un.S_addr = INADDR_ANY; // accept any address + saServer.sin_port = htons(port); // port to listen to + + if (bind(serversocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr))==SOCKET_ERROR){ + sprintf(message, "Could not bind to port %d\n" + "[Is there another server running on that port?]", port); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Port %d is opened", port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + // SOMAXCONN connections in queque? maybe 1 is enough... + if (listen(serversocket, SOMAXCONN) == SOCKET_ERROR){ + sprintf(message, "Listening for a connection failed\n" + "[dunno?]"); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Listening for a connection to establish..."); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + cpuRegs.CP0.n.EPC=cpuRegs.pc; + psxRegs.CP0.n.EPC=psxRegs.pc; + sprintf(message, "%08X", cpuRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), message); + sprintf(message, "%08X", psxRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), message); + sprintf(message, "%d", cpuRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), message); + sprintf(message, "%d", psxRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), message); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGEE), (debuggedCpu==0)); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGIOP), (debuggedCpu==1)); + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAT), 8); //8 hex digits + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAFTER), 10);//10 decimal digits + sprintf(message, "%08X", breakAddress); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAT), message); + sprintf(message, "%d", breakCycle); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), message); + + Button_Enable(GetDlgItem(hDlg, IDC_DEBUGIOP), FALSE);//////////////////////// + + return TRUE; +} + +int readData(char *buffer){ + int r, count=0; + u8 *p=buffer; + + memset(buffer, 0, BUFFERSIZE); + while (((count+= r = recv(remote, p, BUFFERSIZE, 0))!=INVALID_SOCKET) && + (count<*(u16*)buffer)) + p+=r; + + if (r==INVALID_SOCKET) + return 0; + + return count; +} + +int writeData(char *result){ + int r;/*, i; + static char l[300], p[10]; + DECI2_HEADER *header=(DECI2_HEADER*)result; +*/ + r = send(remote, result, *(u16*)result, 0); + if (r==SOCKET_ERROR) + return 0; +/* + sprintf(l, "size=%d, src=%c dst=%c proto=0x%04X ", + header->length-8, header->source, header->destination, header->protocol); + for (i=8; i<*(u16*)result; i++){ + sprintf(p, "%02X ", result[i]); + strcat(l, p); + } + SysMessage(l); +*/ + return r; +} + +DWORD WINAPI ServingFunction(LPVOID lpParam){ + static u8 buffer[BUFFERSIZE], //a big buffer + result[BUFFERSIZE], //a big buffer + eepc[9], ioppc[9], eecy[15], iopcy[15]; + SOCKADDR_IN saClient; + HWND hDlg=(HWND)lpParam; + DWORD size=sizeof(struct sockaddr); + int exit=FALSE; + + if ((remote = accept(serversocket, (struct sockaddr*)&saClient, &size))==INVALID_SOCKET){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Commmunication lost. THE END"); + return FALSE; + } + sprintf(message, "[PCSX2] Connected to %d.%d.%d.%d on remote port %d", + saClient.sin_addr.S_un.S_un_b.s_b1, + saClient.sin_addr.S_un.S_un_b.s_b2, + saClient.sin_addr.S_un.S_un_b.s_b3, + saClient.sin_addr.S_un.S_un_b.s_b4, + saClient.sin_port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Start serving..."); + connected=1;//from this point on, all log stuff goes to ttyp + + //sendBREAK('E', 0, 0xff, 0x21, 1); //do not enable this unless you know what you are doing! + while (!exit && readData(buffer)){ + DECI2_HEADER *header=(DECI2_HEADER*)buffer; + + switch(header->protocol){ + case 0x0000:exit=TRUE; break; + case PROTO_DCMP:D2_DCMP(buffer, result, message); break; +// case 0x0120:D2_DRFP_EE(buffer, result, message); break; +// case 0x0121:D2_DRFP_IOP(buffer, result, message); break; +// case 0x0122:break; + case PROTO_IDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy); break; +// case 0x0140:break; + case PROTO_ILOADP:D2_ILOADP(buffer, result, message); break; + case PROTO_EDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy);break; +// case 0x0240:break; + case PROTO_NETMP:D2_NETMP(buffer, result, message); break; + default: + sprintf(message, "[DECI2 %c->%c/%04X] Protocol=0x%04X", + header->source, header->destination, + header->length, header->protocol); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + continue; + } + if (exit==FALSE){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), eepc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), ioppc); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), eecy); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), iopcy); + } + } + connected=0; + + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Connection closed. THE END"); + return TRUE; +} + +DWORD WINAPI Run2(LPVOID lpParam){ + HWND hDlg=(HWND)lpParam; + static char pc[9]; + int i; + + while (1){ + if (runStatus==RUN){ + if (PSMu32(cpuRegs.pc)==0x0000000D){ + sendBREAK('E', 0, runCode, 0x22, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((runCode==2) && (//next + ((PSMu32(cpuRegs.pc) & 0xFC000000)==0x0C000000) ||//JAL + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x00000009) ||//JALR + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C) //SYSCALL + )){u32 tmppc=cpuRegs.pc, skip=(PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C ? 4 : 8; + while (cpuRegs.pc!=tmppc+skip) + Cpu->Step(); + }else + Cpu->Step(); //use this with breakpoints & step-by-step +// Cpu->ExecuteBlock(); //use this to run faster, but not for stepping +// sprintf(pc, "%08X", cpuRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), pc); +// sprintf(pc, "%08X", psxRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), pc); +// sprintf(pc, "%d", cpuRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), pc); +// sprintf(pc, "%d", psxRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), pc); + if (runCount!=0 && --runCount==0){ + sendBREAK('E', 0, runCode, 0x23, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakAddress) && (breakAddress==cpuRegs.pc)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakCycle) && (breakCycle==cpuRegs.cycle)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + breakCycle=0; + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), "0"); + continue; + } + for (i=0; i +#include +#include + +#define BUFFERSIZE (128*1024) + +extern LRESULT WINAPI RemoteDebuggerParamsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern LRESULT WINAPI RemoteDebuggerProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/windows/VCprojects/pcsx2_2003.sln b/windows/VCprojects/pcsx2_2003.sln new file mode 100644 index 0000000000..78bd7db09f --- /dev/null +++ b/windows/VCprojects/pcsx2_2003.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2003.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Debug TLB = Debug TLB + Release = Release + Release (to Public) = Release (to Public) + Release TLB = Release TLB + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.ActiveCfg = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.Build.0 = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.Build.0 = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).ActiveCfg = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).Build.0 = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.Build.0 = Release TLB|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/windows/VCprojects/pcsx2_2003.vcproj b/windows/VCprojects/pcsx2_2003.vcproj new file mode 100644 index 0000000000..3ec08e4d75 --- /dev/null +++ b/windows/VCprojects/pcsx2_2003.vcproj @@ -0,0 +1,1216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/VCprojects/pcsx2_2005.sln b/windows/VCprojects/pcsx2_2005.sln new file mode 100644 index 0000000000..2bd41451bb --- /dev/null +++ b/windows/VCprojects/pcsx2_2005.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug TLB|Win32 = Debug TLB|Win32 + Debug|Win32 = Debug|Win32 + Release TLB|Win32 = Release TLB|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.ActiveCfg = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.Build.0 = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.Build.0 = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/windows/VCprojects/pcsx2_2005.vcproj b/windows/VCprojects/pcsx2_2005.vcproj new file mode 100644 index 0000000000..4c03861efc --- /dev/null +++ b/windows/VCprojects/pcsx2_2005.vcproj @@ -0,0 +1,1439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/VCprojects/pcsx2_2005beta1_64bits.sln b/windows/VCprojects/pcsx2_2005beta1_64bits.sln new file mode 100644 index 0000000000..98a5f3035a --- /dev/null +++ b/windows/VCprojects/pcsx2_2005beta1_64bits.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005beta1_64bits.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win64 (AMD64) = Debug|Win64 (AMD64) + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj b/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj new file mode 100644 index 0000000000..1c3da07f90 --- /dev/null +++ b/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/Win32.h b/windows/Win32.h new file mode 100644 index 0000000000..607396d356 --- /dev/null +++ b/windows/Win32.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIN32_H__ +#define __WIN32_H__ + +extern int needReset; + +AppData gApp; +HWND hStatusWnd; + +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); +void CreateMainWindow(int nCmdShow); +void RunGui(); +int LoadConfig(); +void SaveConfig(); + +BOOL Open_File_Proc(char *filename); +BOOL Pcsx2Configure(HWND hWnd); +void RunExecute(int run); +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); +void OpenConsole(); +void CloseConsole(); +#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text); + +//patch browser window +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +//cpu dialog window +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + diff --git a/windows/WinMain.c b/windows/WinMain.c new file mode 100644 index 0000000000..76e96d34ca --- /dev/null +++ b/windows/WinMain.c @@ -0,0 +1,1849 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "resource.h" +#include "debugger.h" +#include "rdebugger.h" +#include "AboutDlg.h" +#include "McdsDlg.h" + +#include "VU.h" +#include "iCore.h" +#include "iVUzerorec.h" + +#define COMPILEDATE __DATE__ + +static int efile; +char filename[256]; + +static int AccBreak = 0; +int needReset = 1; +unsigned int langsMax; +typedef struct { + char lang[256]; +} _langs; +_langs *langs = NULL; + +void OpenConsole() { + COORD csize; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + SMALL_RECT srect; + + if (gApp.hConsole) return; + AllocConsole(); + SetConsoleTitle(_("Ps2 Output")); + csize.X = 100; + csize.Y = 1024; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), csize); + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); + srect = csbiInfo.srWindow; + srect.Right = srect.Left + 99; + srect.Bottom = srect.Top + 64; + SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); + gApp.hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +} + +void CloseConsole() { + if (gApp.hConsole == NULL) return; + FreeConsole(); gApp.hConsole = NULL; +} +void strcatz(char *dst, char *src) { + int len = strlen(dst) + 1; + strcpy(dst + len, src); +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);//forward def +//------------------- + +void RunExecute(int run) { + SetThreadPriority(GetCurrentThread(), Config.ThPriority); + SetPriorityClass(GetCurrentProcess(), Config.ThPriority == THREAD_PRIORITY_HIGHEST ? ABOVE_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); + + if (needReset == 1) { + SysReset(); + } +#if 0 //weird problem with that comment it for now + if (GSsetWindowInfo != NULL) { + winInfo info; + + info.hWnd = gApp.hWnd; + info.hMenu = gApp.hMenu; + info.hStatusWnd = hStatusWnd; + + if (GSsetWindowInfo(&info) != FALSE) { + SetMenu(gApp.hWnd, NULL); + ShowWindow(hStatusWnd, SW_HIDE); + ShowWindow(gApp.hWnd, SW_NORMAL); + } else { + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + } + } else { +#endif + AccBreak = 1; + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + //} + if (OpenPlugins() == -1) { + CreateMainWindow(SW_SHOWNORMAL); + return; + } + + if (needReset == 1) { + cpuExecuteBios(); + if (efile == 2) + efile=GetPS2ElfName(filename); + if (efile) + loadElfFile(filename); + efile=0; + needReset = 0; + } + if (run) Cpu->Execute(); +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + int i; + + for (i=0; i<5; i++) { + if (Slots[i] == -1) + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_GRAYED); + else + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_ENABLED); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf (str, "sstates\\%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); + if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + StatusSet(Text); + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %d"), num+1); + else sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1); + StatusSet(Text); + + RunExecute(1); +} + +void OnStates_LoadOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + ret = LoadState(szFileName); + + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Saving State %s"), szFileName); + StatusSet(Text); + + Cpu->Execute(); + } +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +void OnStates_SaveOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + ret = SaveState(szFileName); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Loaded State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Loading State %s"), szFileName); + StatusSet(Text); + + RunExecute(1); + } +} + +#ifdef PCSX2_DEVBUILD + +TESTRUNARGS g_TestRun; + +static int ParseCommandLine(char* pcmd) +{ + const char* pdelim = " \t\r\n"; + char* token = strtok(pcmd, pdelim); + + g_TestRun.efile = 1; + + while(token != NULL) { + + if( stricmp(token, "-help") == 0) { + MessageBox(NULL, "pcsx2 [-option value]\n" + "\tPcsx2 Team 2003-2006\n\n" + "-help {display this help file}\n" + "-title [name] {run this image/iso/elf}\n" + "-image [name] {path and base name of image (do not include the .ext)}\n" + "-log [name] {log path to save log file in}\n" + "-logopt [hex] {log options in hex (see debug.h) }\n" + "-pad [tsxcal] {specify to hold down on the triangle, square, circle, x, start, select buttons}\n" + "-frame [frame] {game will run up to this frame before exiting}\n" + "-numimages [num] {after hitting frame, this many images will be captures every 20 frames}\n" + "-jpg {save images to jpg format}\n" + "-efile [efile] {0 - reset, 1 - runcd (default), 2 - loadelf}\n" + "-gs [dllpath] {specify the dll load path of the GS plugin}\n" + "-cdvd [dllpath] {specify the dll load path of the CDVD plugin}\n" + "-spu [dllpath] {specify the dll load path of the SPU2 plugin}\n", + "Help", MB_OK); + return -1; + } + else if( stricmp(token, "-title") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.ptitle = token; + } + else if( stricmp(token, "-image") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pimagename = token; + } + else if( stricmp(token, "-log") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.plogname = token; + } + else if( stricmp(token, "-logopt") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + if( token[0] == '0' && token[1] == 'x' ) token += 2; + sscanf(token, "%x", &varLog); + } + } + else if( stricmp(token, "-pad") == 0 ) { + token = strtok(NULL, pdelim); + printf("-pad ignored\n"); + } + else if( stricmp(token, "-frame") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.frame = atoi(token); + } + } + else if( stricmp(token, "-numimages") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.numimages = atoi(token); + } + } + else if( stricmp(token, "-efile") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.efile = atoi(token); + } + } + else if( stricmp(token, "-jpg") == 0 ) { + g_TestRun.jpgcapture = 1; + } + else if( stricmp(token, "-gs") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pgsdll = token; + } + else if( stricmp(token, "-cdvd") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pcdvddll = token; + } + else if( stricmp(token, "-spu") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pspudll = token; + } + else { + printf("invalid args\n"); + return -1; + } + + if( token == NULL ) { + printf("invalid args\n"); + return -1; + } + + token = strtok(NULL, pdelim); + } + + if( g_TestRun.ptitle != NULL ) + g_TestRun.enabled = 1; + + return 0; +} + +#endif + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + char *lang; + int i; + +#ifdef WIN32_VIRTUAL_MEM + LPVOID lpMemReserved; + + if( !SysLoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) ) + return 0; + + lpMemReserved = VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); + + if( lpMemReserved == NULL || lpMemReserved!= PS2MEM_BASE ) { + char str[255]; + sprintf(str, "Cannot allocate mem addresses 0x20000000-0x40000000, err: %d", GetLastError()); + MessageBox(NULL, str, "SysError", MB_OK); + return 0; + } +#endif + + gApp.hInstance = hInstance; + gApp.hMenu = NULL; + gApp.hWnd = NULL; + gApp.hConsole = NULL; + +#ifdef ENABLE_NLS + bindtextdomain(PACKAGE, "Langs\\"); + textdomain(PACKAGE); +#endif + + if (LoadConfig() == -1) { + memset(&Config, 0, sizeof(Config)); + //strcpy(Config.Bios, "HLE"); + strcpy(Config.BiosDir, "Bios\\"); + strcpy(Config.PluginsDir, "Plugins\\"); + Config.Patch = 1; + + SysMessage(_("Pcsx2 needs to be configured")); + Pcsx2Configure(NULL); + + return 0; + } + if (Config.Lang[0] == 0) { + strcpy(Config.Lang, "en_US"); + } + + langs = (_langs*)malloc(sizeof(_langs)); + strcpy(langs[0].lang, "en_US"); + InitLanguages(); i=1; + while ((lang = GetLanguageNext()) != NULL) { + langs = (_langs*)realloc(langs, sizeof(_langs)*(i+1)); + strcpy(langs[i].lang, lang); + i++; + } + CloseLanguages(); + langsMax = i; + + if (Config.PsxOut) OpenConsole(); + +#ifdef PCSX2_DEVBUILD + memset(&g_TestRun, 0, sizeof(g_TestRun)); + + if( lpCmdLine == NULL || *lpCmdLine == 0 ) + SysPrintf("-help to see arguments\n"); + else if( ParseCommandLine(lpCmdLine) == -1 ) { + return 2; + } + + if( g_TestRun.pgsdll ) + _snprintf(Config.GS, sizeof(Config.GS), "%s", g_TestRun.pgsdll); + if( g_TestRun.pcdvddll ) + _snprintf(Config.CDVD, sizeof(Config.CDVD), "%s", g_TestRun.pcdvddll); + if( g_TestRun.pspudll ) + _snprintf(Config.SPU2, sizeof(Config.SPU2), "%s", g_TestRun.pspudll); +#endif + + if (SysInit() == -1) return 1; + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled ) { + // run without ui + _snprintf(filename, sizeof(filename), "%s", g_TestRun.ptitle); + needReset = 1; + efile = g_TestRun.efile; + RunExecute(1); + SysClose(); + return 0; // success! + } +#endif + + CreateMainWindow(nCmdShow); + + RunGui(); + +#ifdef WIN32_VIRTUAL_MEM + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); +#endif + + return 0; +} + +void RunGui() { + MSG msg; + + for (;;) { + if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + Sleep(10); + } +} + +#define NUM_STATES 10 +int StatesC = 0; +extern void iDumpRegisters(u32 startpc, u32 temp); + +void CALLBACK KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + switch (ev->key) { + case VK_F1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); + break; + case VK_F2: + if( (GetKeyState(VK_SHIFT)&0x8000) ) + StatesC = (StatesC+NUM_STATES-1)%NUM_STATES; + else + StatesC = (StatesC+1)%NUM_STATES; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); + if( GSchangeSaveState != NULL ) { + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + GSchangeSaveState(StatesC, Text); + } + break; + case VK_F3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); + break; + // note: VK_F5-VK_F7 are reserved for GS + case VK_F8: + GSmakeSnapshot("snap\\"); + break; + +#ifdef PCSX2_DEVBUILD + case VK_F11: + { + int num; + FILE* f; + BASEBLOCKEX** ppblocks = GetAllBaseBlocks(&num, 0); + + f = fopen("perflog.txt", "w"); + while(num-- > 0 ) { + if( ppblocks[0]->visited > 0 ) { + fprintf(f, "%u %u %u %u\n", ppblocks[0]->startpc, (u32)(ppblocks[0]->ltime.QuadPart / ppblocks[0]->visited), ppblocks[0]->visited, ppblocks[0]->size); + } + ppblocks[0]->visited = 0; + ppblocks[0]->ltime.QuadPart = 0; + ppblocks++; + } + fclose(f); + SysPrintf("perflog.txt written\n"); + break; + } + case VK_F12: + iDumpRegisters(cpuRegs.pc, 0); + SysPrintf("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc); + break; +#endif + + case VK_ESCAPE: + ClosePlugins(); + CreateMainWindow(SW_SHOWNORMAL); + RunGui(); + break; + default: + GSkeyEvent(ev); + break; + } +} + +#ifdef PCSX2_DEVBUILD + +BOOL APIENTRY LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { + int i; + switch (message) { + case WM_INITDIALOG: + for (i=0; i<32; i++) + if (varLog & (1<= ID_LANGS && LOWORD(wParam) <= (ID_LANGS + langsMax)) { + AccBreak = 1; + DestroyWindow(gApp.hWnd); + ChangeLanguage(langs[LOWORD(wParam) - ID_LANGS].lang); + CreateMainWindow(SW_NORMAL); + return TRUE; + } + } + break; + case WM_DESTROY: + if (!AccBreak) { + SysClose(); + DeleteObject(hbitmap_background); + PostQuitMessage(0); + exit(0); + } else AccBreak = 0; + return TRUE; + + case WM_QUIT: + if (Config.PsxOut) CloseConsole(); + exit(0); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + return FALSE; +} + +#define _ADDSUBMENU(menu, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDSUBMENU(menun, string) \ + _ADDSUBMENU(gApp.hMenu, menun, string); + +#define ADDSUBMENUS(submn, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + InsertMenu(submenu[submn], 0, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDMENUITEM(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDMENUITEMC(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED | MFS_CHECKED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDSEPARATOR(menun) \ + item.fMask = MIIM_TYPE; \ + item.fType = MFT_SEPARATOR; \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +void CreateMainMenu() { + MENUITEMINFO item; + HMENU submenu[5]; + char buf[256]; + int i; + + item.cbSize = sizeof(MENUITEMINFO); + item.dwTypeData = buf; + item.cch = 256; + + gApp.hMenu = CreateMenu(); + + //submenu = CreatePopupMenu(); + //AppendMenu(gApp.hMenu, MF_STRING | MF_POPUP, (UINT)submenu, _("&File")); + ADDSUBMENU(0, _("&File")); + ADDMENUITEM(0, _("E&xit"), ID_FILE_EXIT); + ADDSEPARATOR(0); + ADDSUBMENUS(0, 1, _("&States")); + ADDSEPARATOR(0); + ADDMENUITEM(0, _("&Open ELF File"), ID_FILEOPEN); + ADDMENUITEM(0, _("&Run CD"), ID_FILE_RUNCD); + ADDSUBMENUS(1, 3, _("&Save")); + ADDSUBMENUS(1, 2, _("&Load")); + ADDMENUITEM(2, _("&Other..."), ID_FILE_STATES_LOAD_OTHER); + ADDMENUITEM(2, _("Slot &5"), ID_FILE_STATES_LOAD_SLOT5); + ADDMENUITEM(2, _("Slot &4"), ID_FILE_STATES_LOAD_SLOT4); + ADDMENUITEM(2, _("Slot &3"), ID_FILE_STATES_LOAD_SLOT3); + ADDMENUITEM(2, _("Slot &2"), ID_FILE_STATES_LOAD_SLOT2); + ADDMENUITEM(2, _("Slot &1"), ID_FILE_STATES_LOAD_SLOT1); + ADDMENUITEM(3, _("&Other..."), ID_FILE_STATES_SAVE_OTHER); + ADDMENUITEM(3, _("Slot &5"), ID_FILE_STATES_SAVE_SLOT5); + ADDMENUITEM(3, _("Slot &4"), ID_FILE_STATES_SAVE_SLOT4); + ADDMENUITEM(3, _("Slot &3"), ID_FILE_STATES_SAVE_SLOT3); + ADDMENUITEM(3, _("Slot &2"), ID_FILE_STATES_SAVE_SLOT2); + ADDMENUITEM(3, _("Slot &1"), ID_FILE_STATES_SAVE_SLOT1); + + ADDSUBMENU(0, _("&Run")); + + ADDSUBMENUS(0, 1, _("&Process Priority")); + ADDMENUITEM(1, _("&Low"), ID_PROCESSLOW ); + ADDMENUITEM(1, _("High"), ID_PROCESSHIGH); + ADDMENUITEM(1, _("Normal"), ID_PROCESSNORMAL); + ADDMENUITEM(0,_("&Arguments"), ID_RUN_CMDLINE); + ADDMENUITEM(0,_("Re&set"), ID_RUN_RESET); + ADDMENUITEM(0,_("E&xecute"), ID_RUN_EXECUTE); + + ADDSUBMENU(0,_("&Config")); +#ifdef PCSX2_DEVBUILD + ADDMENUITEM(0,_("&Advanced"), ID_CONFIG_ADVANCED); +#endif + ADDMENUITEM(0,_("&Patches"), ID_PATCHBROWSER); + ADDMENUITEM(0,_("C&pu"), ID_CONFIG_CPU); + ADDMENUITEM(0,_("&Memcards"), ID_CONFIG_MEMCARDS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("Fire&Wire"), ID_CONFIG_FW); + ADDMENUITEM(0,_("U&SB"), ID_CONFIG_USB); + ADDMENUITEM(0,_("D&ev9"), ID_CONFIG_DEV9); + ADDMENUITEM(0,_("C&dvdrom"), ID_CONFIG_CDVDROM); + ADDMENUITEM(0,_("&Sound"), ID_CONFIG_SOUND); + ADDMENUITEM(0,_("C&ontrollers"), ID_CONFIG_CONTROLLERS); + ADDMENUITEM(0,_("&Graphics"), ID_CONFIG_GRAPHICS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("&Configure"), ID_CONFIG_CONFIGURE); + + ADDSUBMENU(0,_("&Language")); + + for (i=langsMax-1; i>=0; i--) { + if (!strcmp(Config.Lang, langs[i].lang)) { + ADDMENUITEMC(0,ParseLang(langs[i].lang), ID_LANGS + i); + } else { + ADDMENUITEM(0,ParseLang(langs[i].lang), ID_LANGS + i); + } + } + +#ifdef PCSX2_DEVBUILD + ADDSUBMENU(0, _("&Debug")); + ADDMENUITEM(0,_("&Logging"), ID_DEBUG_LOGGING); + ADDMENUITEM(0,_("Memory Dump"), ID_DEBUG_MEMORY_DUMP); + ADDMENUITEM(0,_("&Remote Debugging"), ID_DEBUG_REMOTEDEBUGGING); + ADDMENUITEM(0,_("Enter &Debugger..."), ID_DEBUG_ENTERDEBUGGER); +#endif + + ADDSUBMENU(0, _("&Misc")); + ADDMENUITEM(0,("Enable &Patches"), ID_PATCHES); + ADDMENUITEM(0,("Enable &Console"), ID_CONSOLE); + + + ADDSUBMENU(0, _("&Help")); + ADDMENUITEM(0,_("&Compatibility List..."), ID_HELP_HELP); + ADDMENUITEM(0,_("&About..."), ID_HELP_ABOUT); + +#ifndef PCSX2_DEVBUILD + EnableMenuItem(GetSubMenu(gApp.hMenu, 4), ID_DEBUG_LOGGING, MF_GRAYED); +#endif +} + +void CreateMainWindow(int nCmdShow) { + WNDCLASS wc; + HWND hWnd; + char buf[256]; + char COMPILER[20]=""; + BITMAP bm; + RECT rect; + int w, h; + +#ifdef _MSC_VER + sprintf(COMPILER, "(VC%d)", (_MSC_VER+100)/200);//hacky:) works for VC6 & VC.NET +#elif __BORLANDC__ + sprintf(COMPILER, "(BC)"); +#endif + /* Load Background Bitmap from the ressource */ + hbitmap_background = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + + wc.lpszClassName = "PCSX2 Main"; + wc.lpfnWndProc = MainWndProc; + wc.style = 0; + wc.hInstance = gApp.hInstance; + wc.hIcon = LoadIcon(gApp.hInstance, MAKEINTRESOURCE(IDI_ICON)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_MENUTEXT); + wc.lpszMenuName = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + + RegisterClass(&wc); + GetObject(hbitmap_background, sizeof(bm), &bm); + + { +#ifdef WIN32_VIRTUAL_MEM + const char* pvm = "VM"; +#else + const char* pvm = "non VM"; +#endif + +#ifdef PCSX2_DEVBUILD + sprintf(buf, _("PCSX2 %s Watermoose - %s Compile Date - %s %s"), PCSX2_VERSION, pvm, COMPILEDATE, COMPILER); +#else + sprintf(buf, _("PCSX2 %s Watermoose - %s"), PCSX2_VERSION, pvm); +#endif + } + + hWnd = CreateWindow("PCSX2 Main", + buf, WS_OVERLAPPED | WS_SYSMENU, + 20, 20, 320, 240, NULL, NULL, + gApp.hInstance, NULL); + + gApp.hWnd = hWnd; + ResetMenuSlots(); + CreateMainMenu(); + + SetMenu(gApp.hWnd, gApp.hMenu); + if(Config.ThPriority==THREAD_PRIORITY_NORMAL) CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_HIGHEST) CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_LOWEST) CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); + if(Config.PsxOut) CheckMenuItem(gApp.hMenu,ID_CONSOLE,MF_CHECKED); + if(Config.Patch) CheckMenuItem(gApp.hMenu,ID_PATCHES,MF_CHECKED); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "PCSX2 %s", PCSX2_VERSION); + StatusSet(buf); + + w = bm.bmWidth; h = bm.bmHeight; + GetWindowRect(hStatusWnd, &rect); + h+= rect.bottom - rect.top; + GetMenuItemRect(hWnd, gApp.hMenu, 0, &rect); + h+= rect.bottom - rect.top; + MoveWindow(hWnd, 20, 20, w, h, TRUE); + + DestroyWindow(hStatusWnd); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot", PCSX2_VERSION); + StatusSet(buf); + ShowWindow(hWnd, nCmdShow); + SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} + +BOOL Open_File_Proc(char * filename) { + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "ELF Files (*.ELF)\0*.ELF\0ALL Files (*.*)\0*.*\0"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "ELF"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName(&ofn)) { + struct stat buf; + + if (stat(szFileName, &buf) != 0) { + return FALSE; + } + + strcpy(filename, szFileName); + return TRUE; + } + + return FALSE; +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + SetWindowText(hDlg, _("Program arguments")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Button_SetText(GetDlgItem(hDlg, IDCANCEL), _("Cancel")); + Static_SetText(GetDlgItem(hDlg, IDC_TEXT), _("Fill in the command line arguments for opened program:")); + Static_SetText(GetDlgItem(hDlg, IDC_TIP), _("Tip: If you don't know what to write\nleave it blank")); + + SetDlgItemText(hDlg, IDC_CMDLINE, args); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + char tmp[256]; + + GetDlgItemText(hDlg, IDC_CMDLINE, tmp, 256); + + ZeroMemory(args, 256); + strcpy(args, tmp); + args[255]=0; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +WIN32_FIND_DATA lFindData; +HANDLE lFind; +int lFirst; + +void InitLanguages() { + lFind = FindFirstFile("Langs\\*", &lFindData); + lFirst = 1; +} + +char *GetLanguageNext() { + for (;;) { + if (!strcmp(lFindData.cFileName, ".")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + if (!strcmp(lFindData.cFileName, "..")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + break; + } + if (lFirst == 0) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + } else lFirst = 0; + if (lFind==INVALID_HANDLE_VALUE) return NULL; + + return lFindData.cFileName; +} + +void CloseLanguages() { + if (lFind!=INVALID_HANDLE_VALUE) FindClose(lFind); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +//------------------- + +static int sinit=0; + +int SysInit() { + CreateDirectory("memcards", NULL); + CreateDirectory("sstates", NULL); +#ifdef EMU_LOG + CreateDirectory("logs", NULL); + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.plogname != NULL ) + emuLog = fopen(g_TestRun.plogname, "w"); + if( emuLog == NULL ) + emuLog = fopen("logs\\emuLog.txt","w"); +#endif + + if( emuLog != NULL ) + setvbuf(emuLog, NULL, _IONBF, 0); + +#endif + if (cpuInit() == -1) return -1; + + while (LoadPlugins() == -1) { + if (Pcsx2Configure(NULL) == FALSE) { + exit(1); + } + } + + sinit=1; + + return 0; +} + +void SysReset() { + if (sinit == 0) return; + StatusSet(_("Resetting...")); + cpuReset(); + StatusSet(_("Ready")); +} + + +void SysClose() { + if (sinit == 0) return; + cpuShutdown(); + ReleasePlugins(); + sinit=0; +} + +int concolors[] = { + 0, + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_GREEN | FOREGROUND_RED, + FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE +}; + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + char *ptr; + DWORD tmp; + int len, s; + int i, j; + + if (Config.PsxOut == 0) return; + + va_start(list,fmt); + _vsnprintf(msg,511,fmt,list); + msg[511] = '\0'; + va_end(list); + + ptr = msg; len = strlen(msg); + for (i=0, j=0; i 0x7ffe) // String is too large + return FALSE; + } + + // Store the string. + pLsaString->Buffer = (WCHAR *)pwszString; + pLsaString->Length = (USHORT)dwLen * sizeof(WCHAR); + pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR); + + return TRUE; +} + +PLSA_TRANSLATED_SID2 GetSIDInformation (LPWSTR AccountName,LSA_HANDLE PolicyHandle) +{ + LSA_UNICODE_STRING lucName; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + PLSA_REFERENCED_DOMAIN_LIST lrdlDomainList; + //LSA_TRUST_INFORMATION myDomain; + NTSTATUS ntsResult; + PWCHAR DomainString = NULL; + + // Initialize an LSA_UNICODE_STRING with the name. + if (!InitLsaString(&lucName, AccountName)) + { + wprintf(L"Failed InitLsaString\n"); + return NULL; + } + + ntsResult = LsaLookupNames2( + PolicyHandle, // handle to a Policy object + 0, + 1, // number of names to look up + &lucName, // pointer to an array of names + &lrdlDomainList, // receives domain information + <sTranslatedSID // receives relative SIDs + ); + if (0 != ntsResult) + { + wprintf(L"Failed LsaLookupNames - %lu \n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + + // Get the domain the account resides in. +// myDomain = lrdlDomainList->Domains[ltsTranslatedSID->DomainIndex]; +// DomainString = (PWCHAR) LocalAlloc(LPTR, myDomain.Name.Length + 1); +// wcsncpy(DomainString, myDomain.Name.Buffer, myDomain.Name.Length); + + // Display the relative Id. +// wprintf(L"Relative Id is %lu in domain %ws.\n", +// ltsTranslatedSID->RelativeId, +// DomainString); + + LsaFreeMemory(lrdlDomainList); + + return ltsTranslatedSID; +} + +BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle) +{ + LSA_UNICODE_STRING lucPrivilege; + NTSTATUS ntsResult; + + // Create an LSA_UNICODE_STRING for the privilege name(s). + if (!InitLsaString(&lucPrivilege, L"SeLockMemoryPrivilege")) + { + wprintf(L"Failed InitLsaString\n"); + return FALSE; + } + + ntsResult = LsaAddAccountRights( + PolicyHandle, // An open policy handle. + AccountSID, // The target SID. + &lucPrivilege, // The privilege(s). + 1 // Number of privileges. + ); + if (ntsResult == 0) + { + wprintf(L"Privilege added.\n"); + } + else + { + int err = LsaNtStatusToWinError(ntsResult); + char str[255]; + _snprintf(str, 255, "Privilege was not added - %lu \n", LsaNtStatusToWinError(ntsResult)); + MessageBox(NULL, str, "Privilege error", MB_OK); + return FALSE; + } + + return TRUE; +} + +#define TARGET_SYSTEM_NAME L"mysystem" +LSA_HANDLE GetPolicyHandle() +{ + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR SystemName[] = TARGET_SYSTEM_NAME; + USHORT SystemNameLength; + LSA_UNICODE_STRING lusSystemName; + NTSTATUS ntsResult; + LSA_HANDLE lsahPolicyHandle; + + // Object attributes are reserved, so initialize to zeroes. + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + + //Initialize an LSA_UNICODE_STRING to the server name. + SystemNameLength = wcslen(SystemName); + lusSystemName.Buffer = SystemName; + lusSystemName.Length = SystemNameLength * sizeof(WCHAR); + lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR); + + // Get a handle to the Policy object. + ntsResult = LsaOpenPolicy( + NULL, //Name of the target system. + &ObjectAttributes, //Object attributes. + POLICY_ALL_ACCESS, //Desired access permissions. + &lsahPolicyHandle //Receives the policy handle. + ); + + if (ntsResult != 0) + { + // An error occurred. Display it as a win32 error code. + wprintf(L"OpenPolicy returned %lu\n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + return lsahPolicyHandle; +} + + +/***************************************************************** + LoggedSetLockPagesPrivilege: a function to obtain, if possible, or + release the privilege of locking physical pages. + + Inputs: + + HANDLE hProcess: Handle for the process for which the + privilege is needed + + BOOL bEnable: Enable (TRUE) or disable? + + Return value: TRUE indicates success, FALSE failure. + +*****************************************************************/ +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable) +{ + struct { + u32 Count; + LUID_AND_ATTRIBUTES Privilege [1]; + } Info; + + HANDLE Token; + BOOL Result; + + // Open the token. + + Result = OpenProcessToken ( hProcess, + TOKEN_ADJUST_PRIVILEGES, + & Token); + + if( Result != TRUE ) { + SysPrintf( "Cannot open process token.\n" ); + return FALSE; + } + + // Enable or disable? + + Info.Count = 1; + if( bEnable ) + { + Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + } + else + { + Info.Privilege[0].Attributes = 0; + } + + // Get the LUID. + Result = LookupPrivilegeValue ( NULL, + SE_LOCK_MEMORY_NAME, + &(Info.Privilege[0].Luid)); + + if( Result != TRUE ) + { + SysPrintf( "Cannot get privilege value for %s.\n", SE_LOCK_MEMORY_NAME ); + return FALSE; + } + + // Adjust the privilege. + + Result = AdjustTokenPrivileges ( Token, FALSE, + (PTOKEN_PRIVILEGES) &Info, + 0, NULL, NULL); + + // Check the result. + if( Result != TRUE ) + { + SysPrintf ("Cannot adjust token privileges, error %u.\n", GetLastError() ); + return FALSE; + } + else + { + if( GetLastError() != ERROR_SUCCESS ) + { + + BOOL bSuc = FALSE; + LSA_HANDLE policy; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + + if( !DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_USERNAME), gApp.hWnd, (DLGPROC)UserNameProc) ) + return FALSE; + + policy = GetPolicyHandle(); + + if( policy != NULL ) { + + ltsTranslatedSID = GetSIDInformation(s_szUserName, policy); + + if( ltsTranslatedSID != NULL ) { + bSuc = AddPrivileges(ltsTranslatedSID->Sid, policy); + LsaFreeMemory(ltsTranslatedSID); + } + + LsaClose(policy); + } + + if( bSuc ) { + // Get the LUID. + LookupPrivilegeValue ( NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)); + + bSuc = AdjustTokenPrivileges ( Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL); + } + + if( bSuc ) { + if( MessageBox(NULL, "PCSX2 just changed your SE_LOCK_MEMORY privilege in order to gain access to physical memory.\n" + "Log off/on and run pcsx2 again. Do you want to log off?\n", + "Privilege changed query", MB_YESNO) == IDYES ) { + ExitWindows(EWX_LOGOFF, 0); + } + } + else { + MessageBox(NULL, "Failed adding SE_LOCK_MEMORY privilege, please check the local policy.\n" + "Go to security settings->Local Policies->User Rights. There should be a \"Lock pages in memory\".\n" + "Add your user to that and log off/on. This enables pcsx2 to run at real-time by allocating physical memory.\n" + "Also can try Control Panel->Local Security Policy->... (this does not work on Windows XP Home)\n" + "(zerofrog)\n", "Virtual Memory Access Denied", MB_OK); + return FALSE; + } + } + } + + CloseHandle( Token ); + + return TRUE; +} + +static u32 s_dwPageSize = 0; +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock) +{ + ULONG_PTR NumberOfPagesInitial; // initial number of pages requested + int PFNArraySize; // memory to request for PFN array + BOOL bResult; + + assert( pblock != NULL ); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); + + if( s_dwPageSize == 0 ) { + SYSTEM_INFO sSysInfo; // useful system information + GetSystemInfo(&sSysInfo); // fill the system information structure + s_dwPageSize = sSysInfo.dwPageSize; + + if( s_dwPageSize != 0x1000 ) { + SysMessage("Error! OS page size must be 4Kb!\n" + "If for some reason the OS cannot have 4Kb pages, then will need\n" + "to add a special translation LUT in pcsx2 (which will slow things down a LOT!)"); + return -1; + } + } + + // Calculate the number of pages of memory to request. + pblock->NumberPages = (size+s_dwPageSize-1)/s_dwPageSize; + PFNArraySize = pblock->NumberPages * sizeof (ULONG_PTR); + + pblock->aPFNs = (ULONG_PTR *) HeapAlloc (GetProcessHeap (), 0, PFNArraySize); + + if (pblock->aPFNs == NULL) { + SysPrintf("Failed to allocate on heap.\n"); + goto eCleanupAndExit; + } + + // Allocate the physical memory. + NumberOfPagesInitial = pblock->NumberPages; + bResult = AllocateUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( bResult != TRUE ) + { + SysPrintf("Cannot allocate physical pages, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + if( NumberOfPagesInitial != pblock->NumberPages ) + { + SysPrintf("Allocated only %p of %p pages.\n", pblock->NumberPages, NumberOfPagesInitial ); + goto eCleanupAndExit; + } + + pblock->aVFNs = (ULONG_PTR*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); + + return 0; + +eCleanupAndExit: + SysPhysicalFree(pblock); + return -1; +} + +void SysPhysicalFree(PSMEMORYBLOCK* pblock) +{ + assert( pblock != NULL ); + + // Free the physical pages. + FreeUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( pblock->aPFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aPFNs); + if( pblock->aVFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aVFNs); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); +} + +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + BOOL bResult; + ULONG_PTR i; + + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE ); + if( lpMemReserved == NULL || base != lpMemReserved ) + { + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); + goto eCleanupAndExit; + } + + // Map the physical memory into the window. + bResult = MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); + + for(i = 0; i < pblock->NumberPages; ++i) + pblock->aVFNs[i] = (ULONG_PTR)base + 0x1000*i; + + if( bResult != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to map, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + return 0; + +eCleanupAndExit: + SysVirtualFree(base, size); + return -1; +} + +void SysVirtualFree(void* lpMemReserved, u32 size) +{ + // unmap + if( MapUserPhysicalPages( lpMemReserved, (size+s_dwPageSize-1)/s_dwPageSize, NULL ) != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to unmap, error %u.\n", GetLastError() ); + return; + } + + // Free virtual memory. + VirtualFree( lpMemReserved, 0, MEM_RELEASE ); +} + +void SysVirtualProtectAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + // Reserve the virtual memory. + VirtualProtect( base, size, PAGE_READWRITE, NULL ); + MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); +} + +void SysVirtualProtectFree(void* lpMemReserved, u32 size) +{ + VirtualProtect(lpMemReserved, 0x1000, PAGE_NOACCESS, NULL); + MapUserPhysicalPages( lpMemReserved, size/s_dwPageSize, NULL ); +} + +BOOL SysMapUserPhysicalPages(PVOID Addr, ULONG_PTR NumPages, PULONG_PTR PageArray) +{ + BOOL bResult = MapUserPhysicalPages(Addr, NumPages, PageArray); + +#ifdef _DEBUG + //if( !bResult ) + //__Log("Failed to map user pages: 0x%x:0x%x, error = %d\n", Addr, NumPages, GetLastError()); +#endif + + return bResult; +} + +#else + +#endif \ No newline at end of file diff --git a/windows/afxresmw.h b/windows/afxresmw.h new file mode 100644 index 0000000000..8a4b9df35b --- /dev/null +++ b/windows/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/windows/ini.c b/windows/ini.c new file mode 100644 index 0000000000..9bc404a5b6 --- /dev/null +++ b/windows/ini.c @@ -0,0 +1,173 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* +15-09-2004 : file rewriten for work with inis (shadow) +*/ + +#include +#include +#include +#include "Common.h" +#include "win32.h" +#include + +int LoadConfig() { + FILE *fp; + +#ifdef ENABLE_NLS + char text[256]; + extern int _nl_msg_cat_cntr; +#endif + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return -1; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + fp=fopen("inis\\pcsx2.ini","rt");//check if pcsx2.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + return -1; + } + fclose(fp); + //interface + GetPrivateProfileString("Interface", "Bios", NULL, szValue, 256, szIniFile); + strcpy(Conf->Bios, szValue); + GetPrivateProfileString("Interface", "Lang", NULL, szValue, 256, szIniFile); + strcpy(Conf->Lang, szValue); + GetPrivateProfileString("Interface", "Ps2Out", NULL, szValue, 20, szIniFile); + Conf->PsxOut = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "ThPriority", NULL, szValue, 20, szIniFile); + Conf->ThPriority = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "PluginsDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->PluginsDir, szValue); + GetPrivateProfileString("Interface", "BiosDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->BiosDir, szValue); + GetPrivateProfileString("Interface", "Mcd1", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd1, szValue); + GetPrivateProfileString("Interface", "Mcd2", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd2, szValue); + //plugins + GetPrivateProfileString("Plugins", "GS", NULL, szValue, 256, szIniFile); + strcpy(Conf->GS, szValue); + GetPrivateProfileString("Plugins", "SPU2", NULL, szValue, 256, szIniFile); + strcpy(Conf->SPU2, szValue); + GetPrivateProfileString("Plugins", "CDVD", NULL, szValue, 256, szIniFile); + strcpy(Conf->CDVD, szValue); + GetPrivateProfileString("Plugins", "PAD1", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD1, szValue); + GetPrivateProfileString("Plugins", "PAD2", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD2, szValue); + GetPrivateProfileString("Plugins", "DEV9", NULL, szValue, 256, szIniFile); + strcpy(Conf->DEV9, szValue); + GetPrivateProfileString("Plugins", "USB", NULL, szValue, 256, szIniFile); + strcpy(Conf->USB, szValue); + GetPrivateProfileString("Plugins", "FW", NULL, szValue, 256, szIniFile); + strcpy(Conf->FW, szValue); + //cpu + GetPrivateProfileString("Cpu Options", "Options", NULL, szValue, 20, szIniFile); + Conf->Options= (u32)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Cpu Options", "SafeCnts", NULL, szValue, 20, szIniFile); + Conf->SafeCnts = strtoul(szValue, NULL, 0); + + //Misc + GetPrivateProfileString("Misc", "Patch", NULL, szValue, 20, szIniFile); + Conf->Patch = strtoul(szValue, NULL, 10); + +#ifdef PCSX2_DEVBUILD + GetPrivateProfileString("Misc", "varLog", NULL, szValue, 20, szIniFile); + varLog = strtoul(szValue, NULL, 16); +#endif + +#ifdef ENABLE_NLS + sprintf(text, "LANGUAGE=%s", Conf->Lang); +#ifdef __MSCW32__ + gettext_putenv(text); +#else + putenv(text); +#endif +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + //interface + sprintf(szValue,"%s",Conf->Bios); + WritePrivateProfileString("Interface","Bios",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Lang); + WritePrivateProfileString("Interface","Lang",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PluginsDir); + WritePrivateProfileString("Interface","PluginsDir",szValue,szIniFile); + sprintf(szValue,"%s",Conf->BiosDir); + WritePrivateProfileString("Interface","BiosDir",szValue,szIniFile); + sprintf(szValue,"%u",Conf->PsxOut); + WritePrivateProfileString("Interface","Ps2Out",szValue,szIniFile); + sprintf(szValue,"%u",Conf->ThPriority); + WritePrivateProfileString("Interface","ThPriority",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd1); + WritePrivateProfileString("Interface","Mcd1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd2); + WritePrivateProfileString("Interface","Mcd2",szValue,szIniFile); + //plugins + sprintf(szValue,"%s",Conf->GS); + WritePrivateProfileString("Plugins","GS",szValue,szIniFile); + sprintf(szValue,"%s",Conf->SPU2); + WritePrivateProfileString("Plugins","SPU2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->CDVD); + WritePrivateProfileString("Plugins","CDVD",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD1); + WritePrivateProfileString("Plugins","PAD1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD2); + WritePrivateProfileString("Plugins","PAD2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->DEV9); + WritePrivateProfileString("Plugins","DEV9",szValue,szIniFile); + sprintf(szValue,"%s",Conf->USB); + WritePrivateProfileString("Plugins","USB",szValue,szIniFile); + sprintf(szValue,"%s",Conf->FW); + WritePrivateProfileString("Plugins","FW",szValue,szIniFile); + //cpu + sprintf(szValue,"%u", Conf->Options); + WritePrivateProfileString("Cpu Options","Options",szValue,szIniFile); + sprintf(szValue,"%u",Conf->SafeCnts); + WritePrivateProfileString("Cpu Options","SafeCnts",szValue,szIniFile); + //Misc + sprintf(szValue,"%u",Conf->Patch); + WritePrivateProfileString("Misc","Patch",szValue,szIniFile); + sprintf(szValue,"%x",varLog); + WritePrivateProfileString("Misc","varLog",szValue,szIniFile); + + +} + diff --git a/windows/libs/gnu_gettext.lib b/windows/libs/gnu_gettext.lib new file mode 100644 index 0000000000..8b3885a56b Binary files /dev/null and b/windows/libs/gnu_gettext.lib differ diff --git a/windows/libs/libintlmsc.h b/windows/libs/libintlmsc.h new file mode 100644 index 0000000000..fd5f482026 --- /dev/null +++ b/windows/libs/libintlmsc.h @@ -0,0 +1,116 @@ +/* This file is part of a Windows32 DLL Interface to: + GNU gettext - internationalization aids + Copyright (C) 1996, 1998 Free Software Foundation, Inc. + + This file was written by Franco Bez + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* REPLACEMENT FOR ORIGINAL LIBINTL.H for use with Windows32 */ + +#if !defined(__LIBINTL_H_INCLUDED) +#define __LIBINTL_H_INCLUDED + +#if defined(__cplusplus) +extern "C" { +#endif + +/* See if we allready know what we want static or dll linkage or none at all*/ +#if defined DONT_USE_GETTEXT || ( defined USE_SAFE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) || ( defined USE_GETTEXT_DLL && defined USE_SAFE_GETTEXT_DLL ) || ( defined USE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) +/* TWO IS HARDLY POSSIBLE */ +#undef USE_GETTEXT_DLL +#undef USE_GETTEXT_STATIC +#undefd USE_SAFE_GETTEXT_DLL +#endif /* MORE THAN ONE - OR NONE AT ALL */ + +#if !defined USE_GETTEXT_DLL && !defined USE_SAFE_GETTEXT_DLL && !defined USE_GETTEXT_STATIC && !defined DONT_USE_GETTEXT +/* not explicitly defined so try to guess it - + if GNUC is used - we use static linkage by default + because at the moment this is the only plattform + for which a static lib is available + else we use the DLL built with GNUC */ +# if defined __GNUC__ +# define USE_GETTEXT_STATIC +# else +# define USE_GETTEXT_DLL +# endif /* __GNUC__ */ +#endif /* NONE */ + +/* NOW ONLY ONE OF + DONT_USE_GETTEXT , USE_GETTEXT_DLL , USE_SAFE_GETTEXT_DLL , USE_GETTEXT_STATIC + IS DEFINED */ + +#if defined USE_GETTEXT_DLL +/* exported functions in DLL gnu_gettext.dll + you should link with import library + -lgnu_gettext (for mingw32) OR gnu_gettext.lib (MSVC) */ +__declspec(dllimport) char *gettext(const char *__msgid); +__declspec(dllimport) char *dgettext(const char *__domainname,const char *__msgid); +__declspec(dllimport) char *dcgettext(const char *__domainname,const char *__msgid, int __category); +__declspec(dllimport) char *textdomain(const char *__domainname); +__declspec(dllimport) char *bindtextdomain(const char *__domainname,const char *__dirname); +/* calling _putenv from within the DLL */ +__declspec(dllexport) int gettext_putenv(const char *envstring); +#endif /* DLL */ + +#if defined USE_SAFE_GETTEXT_DLL +/* Uses DLL gnu_gettext.dll ONLY if present, otherwise NO translation will take place + you should link with "safe_gettext_dll.o -lstdc++" see README for safe_gettext_dll for Details */ +/* The safe gettext functions */ +extern char *gettext(const char *szMsgId); +extern char *dgettext(const char *szDomain,const char *szMsgId); +extern char *dcgettext(const char *szDomain,const char *szMsgId,int iCategory); +extern char *textdomain(const char *szDomain); +extern char *bindtextdomain(const char *szDomain,const char *szDirectory); +/* calling _putenv from within the DLL */ +extern int gettext_putenv(const char *envstring); +#endif /* SAFE DLL */ + +#if defined USE_GETTEXT_STATIC +/* exported functions in static library libintl.a + and supporting macros + you should link with -lintl (mingw32) */ +extern char *gettext__(const char *__msgid); +extern char *dgettext__(const char *__domainname,const char *__msgid); +extern char *dcgettext__(const char *__domainname,const char *__msgid, int __category); +extern char *textdomain__(const char *__domainname); +extern char *bindtextdomain__(const char *__domainname,const char *__dirname); +#define gettext(szMsgId) gettext__(szMsgId) +#define dgettext(szDomain,szMsgId) dgettext__(szDomain,szMsgId) +#define dcgettext(szDomain,szMsgId,iCategory) dcgettext__(szDomain,szMsgId,iCategory) +#define textdomain(szDomain) textdomain__(szDomain) +#define bindtextdomain(szDomain,szDirectory) bindtextdomain__(szDomain,szDirectory) +// dummy - for static linkage - calling _putenv from within the DLL +#define gettext_putenv(a) _putenv(a) +#endif /* STATIC */ + +#if defined DONT_USE_GETTEXT +/* DON'T USE GETTEXT AT ALL + MAKROS TO MAKE CODE COMPILE WELL, BUT GETTEXT WILL NOT BE USESD +*/ +# define gettext(Msgid) (Msgid) +# define dgettext(Domainname, Msgid) (Msgid) +# define dcgettext(Domainname, Msgid, Category) (Msgid) +# define textdomain(Domainname) ((char *) Domainname) +# define bindtextdomain(Domainname, Dirname) ((char *) Dirname) +// dummy - for static linkage - calling _putenv from within the DLL +# define gettext_putenv(a) _putenv(a) +#endif /* DON'T USE AT ALL */ + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /*!defined(__LIBINTL_H_INCLUDED)*/ diff --git a/windows/libs/pthread.h b/windows/libs/pthread.h new file mode 100644 index 0000000000..a0add29f5c --- /dev/null +++ b/windows/libs/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,7,0,0 +#define PTW32_VERSION_STRING "2, 7, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/windows/libs/pthreadVC2.lib b/windows/libs/pthreadVC2.lib new file mode 100644 index 0000000000..b447a8b71e Binary files /dev/null and b/windows/libs/pthreadVC2.lib differ diff --git a/windows/libs/sched.h b/windows/libs/sched.h new file mode 100644 index 0000000000..10ecb5d7ea --- /dev/null +++ b/windows/libs/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/windows/libs/semaphore.h b/windows/libs/semaphore.h new file mode 100644 index 0000000000..ea42ce3703 --- /dev/null +++ b/windows/libs/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/windows/mingw/Makefile.win b/windows/mingw/Makefile.win new file mode 100644 index 0000000000..7449952180 --- /dev/null +++ b/windows/mingw/Makefile.win @@ -0,0 +1,348 @@ +# Project: pcsx2 +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//pcsx2_private.res +OBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LINKOBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LIBS = -mwindows -Wall -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -s +INCS = -I"../../" -I"C:/Documents and Settings/shadow/Desktop/Npcsx2" -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +CXXINCS = -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +BIN = pcsx2.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -D__WIN32__ -D__MINGW32__ -O3 -fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing -m128bit-long-double -mfpmath=sse -march=athlon64 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before pcsx2.exe all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CC) $(LINKOBJ) -o "pcsx2.exe" $(LIBS) + +Obj//AboutDlg.o: ../AboutDlg.c + $(CC) -c ../AboutDlg.c -o Obj//AboutDlg.o $(CFLAGS) + +Obj//ConfigDlg.o: ../ConfigDlg.c + $(CC) -c ../ConfigDlg.c -o Obj//ConfigDlg.o $(CFLAGS) + +Obj//CpuDlg.o: ../CpuDlg.c + $(CC) -c ../CpuDlg.c -o Obj//CpuDlg.o $(CFLAGS) + +Obj//Debugger.o: ../Debugger.c + $(CC) -c ../Debugger.c -o Obj//Debugger.o $(CFLAGS) + +Obj//DebugMemory.o: ../DebugMemory.c + $(CC) -c ../DebugMemory.c -o Obj//DebugMemory.o $(CFLAGS) + +Obj//Debugreg.o: ../Debugreg.c + $(CC) -c ../Debugreg.c -o Obj//Debugreg.o $(CFLAGS) + +Obj//ini.o: ../ini.c + $(CC) -c ../ini.c -o Obj//ini.o $(CFLAGS) + +Obj//McdsDlg.o: ../McdsDlg.c + $(CC) -c ../McdsDlg.c -o Obj//McdsDlg.o $(CFLAGS) + +Obj//PatchBrowser.o: ../PatchBrowser.c + $(CC) -c ../PatchBrowser.c -o Obj//PatchBrowser.o $(CFLAGS) + +Obj//RDebugger.o: ../RDebugger.c + $(CC) -c ../RDebugger.c -o Obj//RDebugger.o $(CFLAGS) + +Obj//WinMain.o: ../WinMain.c + $(CC) -c ../WinMain.c -o Obj//WinMain.o $(CFLAGS) + +Obj//Idct.o: ../../IPU/Idct.c + $(CC) -c ../../IPU/Idct.c -o Obj//Idct.o $(CFLAGS) + +Obj//IPU.o: ../../IPU/IPU.c + $(CC) -c ../../IPU/IPU.c -o Obj//IPU.o $(CFLAGS) + +Obj//Mpeg.o: ../../IPU/Mpeg.c + $(CC) -c ../../IPU/Mpeg.c -o Obj//Mpeg.o $(CFLAGS) + +Obj//yuv2rgb.o: ../../IPU/yuv2rgb.c + $(CC) -c ../../IPU/yuv2rgb.c -o Obj//yuv2rgb.o $(CFLAGS) + +Obj//cpuopsDebug.o: ../../DebugTools/cpuopsDebug.c + $(CC) -c ../../DebugTools/cpuopsDebug.c -o Obj//cpuopsDebug.o $(CFLAGS) + +Obj//DisR3000A.o: ../../DebugTools/DisR3000A.c + $(CC) -c ../../DebugTools/DisR3000A.c -o Obj//DisR3000A.o $(CFLAGS) + +Obj//DisR3000asm.o: ../../DebugTools/DisR3000asm.c + $(CC) -c ../../DebugTools/DisR3000asm.c -o Obj//DisR3000asm.o $(CFLAGS) + +Obj//DisR5900.o: ../../DebugTools/DisR5900.c + $(CC) -c ../../DebugTools/DisR5900.c -o Obj//DisR5900.o $(CFLAGS) + +Obj//DisR5900asm.o: ../../DebugTools/DisR5900asm.c + $(CC) -c ../../DebugTools/DisR5900asm.c -o Obj//DisR5900asm.o $(CFLAGS) + +Obj//DisVU0Micro.o: ../../DebugTools/DisVU0Micro.c + $(CC) -c ../../DebugTools/DisVU0Micro.c -o Obj//DisVU0Micro.o $(CFLAGS) + +Obj//DisVU1Micro.o: ../../DebugTools/DisVU1Micro.c + $(CC) -c ../../DebugTools/DisVU1Micro.c -o Obj//DisVU1Micro.o $(CFLAGS) + +Obj//adler32.o: ../../zlib/adler32.c + $(CC) -c ../../zlib/adler32.c -o Obj//adler32.o $(CFLAGS) + +Obj//compress.o: ../../zlib/compress.c + $(CC) -c ../../zlib/compress.c -o Obj//compress.o $(CFLAGS) + +Obj//crc32.o: ../../zlib/crc32.c + $(CC) -c ../../zlib/crc32.c -o Obj//crc32.o $(CFLAGS) + +Obj//deflate.o: ../../zlib/deflate.c + $(CC) -c ../../zlib/deflate.c -o Obj//deflate.o $(CFLAGS) + +Obj//gzio.o: ../../zlib/gzio.c + $(CC) -c ../../zlib/gzio.c -o Obj//gzio.o $(CFLAGS) + +Obj//infback.o: ../../zlib/infback.c + $(CC) -c ../../zlib/infback.c -o Obj//infback.o $(CFLAGS) + +Obj//inffast.o: ../../zlib/inffast.c + $(CC) -c ../../zlib/inffast.c -o Obj//inffast.o $(CFLAGS) + +Obj//inflate.o: ../../zlib/inflate.c + $(CC) -c ../../zlib/inflate.c -o Obj//inflate.o $(CFLAGS) + +Obj//inftrees.o: ../../zlib/inftrees.c + $(CC) -c ../../zlib/inftrees.c -o Obj//inftrees.o $(CFLAGS) + +Obj//trees.o: ../../zlib/trees.c + $(CC) -c ../../zlib/trees.c -o Obj//trees.o $(CFLAGS) + +Obj//uncompr.o: ../../zlib/uncompr.c + $(CC) -c ../../zlib/uncompr.c -o Obj//uncompr.o $(CFLAGS) + +Obj//zutil.o: ../../zlib/zutil.c + $(CC) -c ../../zlib/zutil.c -o Obj//zutil.o $(CFLAGS) + +Obj//iR5900Arit.o: ../../ix86-32/iR5900Arit.c + $(CC) -c ../../ix86-32/iR5900Arit.c -o Obj//iR5900Arit.o $(CFLAGS) + +Obj//iR5900AritImm.o: ../../ix86-32/iR5900AritImm.c + $(CC) -c ../../ix86-32/iR5900AritImm.c -o Obj//iR5900AritImm.o $(CFLAGS) + +Obj//iR5900Branch.o: ../../ix86-32/iR5900Branch.c + $(CC) -c ../../ix86-32/iR5900Branch.c -o Obj//iR5900Branch.o $(CFLAGS) + +Obj//iR5900Jump.o: ../../ix86-32/iR5900Jump.c + $(CC) -c ../../ix86-32/iR5900Jump.c -o Obj//iR5900Jump.o $(CFLAGS) + +Obj//iR5900LoadStore.o: ../../ix86-32/iR5900LoadStore.c + $(CC) -c ../../ix86-32/iR5900LoadStore.c -o Obj//iR5900LoadStore.o $(CFLAGS) + +Obj//iR5900Move.o: ../../ix86-32/iR5900Move.c + $(CC) -c ../../ix86-32/iR5900Move.c -o Obj//iR5900Move.o $(CFLAGS) + +Obj//iR5900MultDiv.o: ../../ix86-32/iR5900MultDiv.c + $(CC) -c ../../ix86-32/iR5900MultDiv.c -o Obj//iR5900MultDiv.o $(CFLAGS) + +Obj//iR5900Shift.o: ../../ix86-32/iR5900Shift.c + $(CC) -c ../../ix86-32/iR5900Shift.c -o Obj//iR5900Shift.o $(CFLAGS) + +Obj//iCP0.o: ../../x86/iCP0.c + $(CC) -c ../../x86/iCP0.c -o Obj//iCP0.o $(CFLAGS) + +Obj//iFPU.o: ../../x86/iFPU.c + $(CC) -c ../../x86/iFPU.c -o Obj//iFPU.o $(CFLAGS) + +Obj//iMMI.o: ../../x86/iMMI.c + $(CC) -c ../../x86/iMMI.c -o Obj//iMMI.o $(CFLAGS) + +Obj//iR3000A.o: ../../x86/iR3000A.c + $(CC) -c ../../x86/iR3000A.c -o Obj//iR3000A.o $(CFLAGS) + +Obj//iR5900.o: ../../x86/iR5900.c + $(CC) -c ../../x86/iR5900.c -o Obj//iR5900.o $(CFLAGS) + +Obj//iVU0micro.o: ../../x86/iVU0micro.c + $(CC) -c ../../x86/iVU0micro.c -o Obj//iVU0micro.o $(CFLAGS) + +Obj//iVU1micro.o: ../../x86/iVU1micro.c + $(CC) -c ../../x86/iVU1micro.c -o Obj//iVU1micro.o $(CFLAGS) + +Obj//iVUmicro.o: ../../x86/iVUmicro.c + $(CC) -c ../../x86/iVUmicro.c -o Obj//iVUmicro.o $(CFLAGS) + +Obj//recCOP2.o: ../../x86/recCOP2.c + $(CC) -c ../../x86/recCOP2.c -o Obj//recCOP2.o $(CFLAGS) + +Obj//ix86.o: ../../x86/ix86/ix86.c + $(CC) -c ../../x86/ix86/ix86.c -o Obj//ix86.o $(CFLAGS) + +Obj//ix86_3dnow.o: ../../x86/ix86/ix86_3dnow.c + $(CC) -c ../../x86/ix86/ix86_3dnow.c -o Obj//ix86_3dnow.o $(CFLAGS) + +Obj//ix86_cpudetect.o: ../../x86/ix86/ix86_cpudetect.c + $(CC) -c ../../x86/ix86/ix86_cpudetect.c -o Obj//ix86_cpudetect.o $(CFLAGS) + +Obj//ix86_fpu.o: ../../x86/ix86/ix86_fpu.c + $(CC) -c ../../x86/ix86/ix86_fpu.c -o Obj//ix86_fpu.o $(CFLAGS) + +Obj//ix86_mmx.o: ../../x86/ix86/ix86_mmx.c + $(CC) -c ../../x86/ix86/ix86_mmx.c -o Obj//ix86_mmx.o $(CFLAGS) + +Obj//ix86_sse.o: ../../x86/ix86/ix86_sse.c + $(CC) -c ../../x86/ix86/ix86_sse.c -o Obj//ix86_sse.o $(CFLAGS) + +Obj//CDVD.o: ../../CDVD.c + $(CC) -c ../../CDVD.c -o Obj//CDVD.o $(CFLAGS) + +Obj//CDVDiso.o: ../../CDVDiso.c + $(CC) -c ../../CDVDiso.c -o Obj//CDVDiso.o $(CFLAGS) + +Obj//CDVDisodrv.o: ../../CDVDisodrv.c + $(CC) -c ../../CDVDisodrv.c -o Obj//CDVDisodrv.o $(CFLAGS) + +Obj//COP0.o: ../../COP0.c + $(CC) -c ../../COP0.c -o Obj//COP0.o $(CFLAGS) + +Obj//Counters.o: ../../Counters.c + $(CC) -c ../../Counters.c -o Obj//Counters.o $(CFLAGS) + +Obj//Decode_XA.o: ../../Decode_XA.c + $(CC) -c ../../Decode_XA.c -o Obj//Decode_XA.o $(CFLAGS) + +Obj//Elfheader.o: ../../Elfheader.c + $(CC) -c ../../Elfheader.c -o Obj//Elfheader.o $(CFLAGS) + +Obj//FiFo.o: ../../FiFo.c + $(CC) -c ../../FiFo.c -o Obj//FiFo.o $(CFLAGS) + +Obj//FPU.o: ../../FPU.c + $(CC) -c ../../FPU.c -o Obj//FPU.o $(CFLAGS) + +Obj//GS.o: ../../GS.c + $(CC) -c ../../GS.c -o Obj//GS.o $(CFLAGS) + +Obj//Gte.o: ../../Gte.c + $(CC) -c ../../Gte.c -o Obj//Gte.o $(CFLAGS) + +Obj//Hw.o: ../../Hw.c + $(CC) -c ../../Hw.c -o Obj//Hw.o $(CFLAGS) + +Obj//Interpreter.o: ../../Interpreter.c + $(CC) -c ../../Interpreter.c -o Obj//Interpreter.o $(CFLAGS) + +Obj//InterTables.o: ../../InterTables.c + $(CC) -c ../../InterTables.c -o Obj//InterTables.o $(CFLAGS) + +Obj//Mdec.o: ../../Mdec.c + $(CC) -c ../../Mdec.c -o Obj//Mdec.o $(CFLAGS) + +Obj//Memory.o: ../../Memory.c + $(CC) -c ../../Memory.c -o Obj//Memory.o $(CFLAGS) + +Obj//Misc.o: ../../Misc.c + $(CC) -c ../../Misc.c -o Obj//Misc.o $(CFLAGS) + +Obj//MMI.o: ../../MMI.c + $(CC) -c ../../MMI.c -o Obj//MMI.o $(CFLAGS) + +Obj//Patch.o: ../../Patch.c + $(CC) -c ../../Patch.c -o Obj//Patch.o $(CFLAGS) + +Obj//Plugins.o: ../../Plugins.c + $(CC) -c ../../Plugins.c -o Obj//Plugins.o $(CFLAGS) + +Obj//PsxBios.o: ../../PsxBios.c + $(CC) -c ../../PsxBios.c -o Obj//PsxBios.o $(CFLAGS) + +Obj//PsxCounters.o: ../../PsxCounters.c + $(CC) -c ../../PsxCounters.c -o Obj//PsxCounters.o $(CFLAGS) + +Obj//PsxDma.o: ../../PsxDma.c + $(CC) -c ../../PsxDma.c -o Obj//PsxDma.o $(CFLAGS) + +Obj//PsxGPU.o: ../../PsxGPU.c + $(CC) -c ../../PsxGPU.c -o Obj//PsxGPU.o $(CFLAGS) + +Obj//PsxHw.o: ../../PsxHw.c + $(CC) -c ../../PsxHw.c -o Obj//PsxHw.o $(CFLAGS) + +Obj//PsxInterpreter.o: ../../PsxInterpreter.c + $(CC) -c ../../PsxInterpreter.c -o Obj//PsxInterpreter.o $(CFLAGS) + +Obj//PsxMem.o: ../../PsxMem.c + $(CC) -c ../../PsxMem.c -o Obj//PsxMem.o $(CFLAGS) + +Obj//PsxSio2.o: ../../PsxSio2.c + $(CC) -c ../../PsxSio2.c -o Obj//PsxSio2.o $(CFLAGS) + +Obj//R3000A.o: ../../R3000A.c + $(CC) -c ../../R3000A.c -o Obj//R3000A.o $(CFLAGS) + +Obj//R5900.o: ../../R5900.c + $(CC) -c ../../R5900.c -o Obj//R5900.o $(CFLAGS) + +Obj//Sif.o: ../../Sif.c + $(CC) -c ../../Sif.c -o Obj//Sif.o $(CFLAGS) + +Obj//Sio.o: ../../Sio.c + $(CC) -c ../../Sio.c -o Obj//Sio.o $(CFLAGS) + +Obj//SPR.o: ../../SPR.c + $(CC) -c ../../SPR.c -o Obj//SPR.o $(CFLAGS) + +Obj//Stats.o: ../../Stats.c + $(CC) -c ../../Stats.c -o Obj//Stats.o $(CFLAGS) + +Obj//Vif.o: ../../Vif.c + $(CC) -c ../../Vif.c -o Obj//Vif.o $(CFLAGS) + +Obj//VifDma.o: ../../VifDma.c + $(CC) -c ../../VifDma.c -o Obj//VifDma.o $(CFLAGS) + +Obj//VU0.o: ../../VU0.c + $(CC) -c ../../VU0.c -o Obj//VU0.o $(CFLAGS) + +Obj//VU0micro.o: ../../VU0micro.c + $(CC) -c ../../VU0micro.c -o Obj//VU0micro.o $(CFLAGS) + +Obj//VU1micro.o: ../../VU1micro.c + $(CC) -c ../../VU1micro.c -o Obj//VU1micro.o $(CFLAGS) + +Obj//VUflags.o: ../../VUflags.c + $(CC) -c ../../VUflags.c -o Obj//VUflags.o $(CFLAGS) + +Obj//VUops.o: ../../VUops.c + $(CC) -c ../../VUops.c -o Obj//VUops.o $(CFLAGS) + +Obj//Cache.o: ../../Cache.c + $(CC) -c ../../Cache.c -o Obj//Cache.o $(CFLAGS) + +Obj//CdRom.o: ../../CdRom.c + $(CC) -c ../../CdRom.c -o Obj//CdRom.o $(CFLAGS) + +Obj//deci2.o: ../../RDebug/deci2.c + $(CC) -c ../../RDebug/deci2.c -o Obj//deci2.o $(CFLAGS) + +Obj//deci2_dbgp.o: ../../RDebug/deci2_dbgp.c + $(CC) -c ../../RDebug/deci2_dbgp.c -o Obj//deci2_dbgp.o $(CFLAGS) + +Obj//deci2_dcmp.o: ../../RDebug/deci2_dcmp.c + $(CC) -c ../../RDebug/deci2_dcmp.c -o Obj//deci2_dcmp.o $(CFLAGS) + +Obj//deci2_iloadp.o: ../../RDebug/deci2_iloadp.c + $(CC) -c ../../RDebug/deci2_iloadp.c -o Obj//deci2_iloadp.o $(CFLAGS) + +Obj//deci2_netmp.o: ../../RDebug/deci2_netmp.c + $(CC) -c ../../RDebug/deci2_netmp.c -o Obj//deci2_netmp.o $(CFLAGS) + +Obj//deci2_ttyp.o: ../../RDebug/deci2_ttyp.c + $(CC) -c ../../RDebug/deci2_ttyp.c -o Obj//deci2_ttyp.o $(CFLAGS) + +Obj//pcsx2_private.res: pcsx2_private.rc ../pcsx2.rc + $(WINDRES) -i pcsx2_private.rc --input-format=rc -o Obj//pcsx2_private.res -O coff --include-dir ../../ --include-dir ../ --include-dir ../mingw diff --git a/windows/mingw/afxres.h b/windows/mingw/afxres.h new file mode 100644 index 0000000000..8a4b9df35b --- /dev/null +++ b/windows/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/windows/mingw/pcsx2.dev b/windows/mingw/pcsx2.dev new file mode 100644 index 0000000000..db8fafbceb --- /dev/null +++ b/windows/mingw/pcsx2.dev @@ -0,0 +1,2116 @@ +[Project] +FileName=pcsx2.dev +Name=pcsx2 +UnitCount=205 +Type=0 +Ver=1 +ObjFiles= +Includes=../..;../../zlib;../../DebugTools;../../IPU;../../x86;../../ix86-32;..;../RDebug +Libs= +PrivateResource=pcsx2_private.rc +ResourceIncludes=../../;../;..\mingw +MakeIncludes= +Compiler=-v_@@_-D__WIN32___@@_-D__MINGW32__ _@@_-Wall _@@_-O3 ${-fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing} -mfpmath=sse -march=athlon64_@@_ _@@_ +CppCompiler= +Linker=-lcomctl32 _@@_-lwsock32 _@@_-lwinmm _@@_-lgdi32 _@@_-lcomdlg32 _@@__@@_-m128bit-long-double_@@_ +IsCpp=0 +Icon= +ExeOutput=../ +ObjectOutput=Obj/ +OverrideOutput=0 +OverrideOutputName=pcsx2.exe +HostApplication= +Folders=cpu,DebugTools,DECI2,GUI,Hardware,IOP_CPU,IPU,ix86,ix86/x86,ix86-32,misc,plugins,Sif,zlib +CommandLine= +UseCustomMakefile=0 +CustomMakefile=..\Makefile +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=..\AboutDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\AboutDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\ConfigDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\CpuDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\Debugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\Debugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\DebugMemory.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\Debugreg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\ini.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\McdsDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\McdsDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\PatchBrowser.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\pcsx2.rc +Folder=GUI +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\RDebugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\RDebugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\resource.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\Win32.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\WinMain.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=afxres.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\..\IPU\Idct.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\..\IPU\IPU.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\..\IPU\IPU.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\..\IPU\Mpeg.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\..\IPU\Mpeg.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\..\IPU\Vlc.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\..\IPU\yuv2rgb.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\..\IPU\yuv2rgb.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\..\DebugTools\cpuopsDebug.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\..\DebugTools\cpuopsDebug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\..\DebugTools\Debug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\..\DebugTools\DisASM.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\..\DebugTools\DisR3000A.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\..\DebugTools\DisR3000asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\..\DebugTools\DisR5900.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\..\DebugTools\DisR5900asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\..\DebugTools\DisVU0Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\..\DebugTools\DisVU1Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\..\DebugTools\DisVUmicro.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\..\DebugTools\DisVUops.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\..\zlib\adler32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\..\zlib\compress.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\..\zlib\crc32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=..\..\zlib\crc32.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit44] +FileName=..\..\zlib\deflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit45] +FileName=..\..\zlib\deflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit46] +FileName=..\..\zlib\gzio.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit47] +FileName=..\..\zlib\infback.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit48] +FileName=..\..\zlib\inffast.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit49] +FileName=..\..\zlib\inffast.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit50] +FileName=..\..\zlib\inffixed.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit51] +FileName=..\..\zlib\inflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit52] +FileName=..\..\zlib\inflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit53] +FileName=..\..\zlib\inftrees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit54] +FileName=..\..\zlib\inftrees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit55] +FileName=..\..\zlib\trees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit56] +FileName=..\..\zlib\trees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit57] +FileName=..\..\zlib\uncompr.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit58] +FileName=..\..\zlib\zconf.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit59] +FileName=..\..\zlib\zlib.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit60] +FileName=..\..\zlib\zutil.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit61] +FileName=..\..\zlib\zutil.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit62] +FileName=..\..\ix86-32\iR5900Arit.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit63] +FileName=..\..\ix86-32\iR5900Arit.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit64] +FileName=..\..\ix86-32\iR5900AritImm.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit65] +FileName=..\..\ix86-32\iR5900AritImm.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit66] +FileName=..\..\ix86-32\iR5900Branch.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit67] +FileName=..\..\ix86-32\iR5900Branch.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit68] +FileName=..\..\ix86-32\iR5900Jump.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit69] +FileName=..\..\ix86-32\iR5900Jump.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit70] +FileName=..\..\ix86-32\iR5900LoadStore.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit71] +FileName=..\..\ix86-32\iR5900LoadStore.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit72] +FileName=..\..\ix86-32\iR5900Move.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit73] +FileName=..\..\ix86-32\iR5900Move.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit74] +FileName=..\..\ix86-32\iR5900MultDiv.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit75] +FileName=..\..\ix86-32\iR5900MultDiv.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit76] +FileName=..\..\ix86-32\iR5900Shift.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit77] +FileName=..\..\ix86-32\iR5900Shift.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit78] +FileName=..\..\x86\iCP0.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit79] +FileName=..\..\x86\iCP0.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit80] +FileName=..\..\x86\iFPU.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit81] +FileName=..\..\x86\iFPU.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit82] +FileName=..\..\x86\iMMI.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit83] +FileName=..\..\x86\iMMI.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit84] +FileName=..\..\x86\iR3000A.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit85] +FileName=..\..\x86\iR5900.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit86] +FileName=..\..\x86\iR5900.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit87] +FileName=..\..\x86\iVU0micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit88] +FileName=..\..\x86\iVU0micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit89] +FileName=..\..\x86\iVU1micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit90] +FileName=..\..\x86\iVU1micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit91] +FileName=..\..\x86\iVUmicro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit92] +FileName=..\..\x86\iVUmicro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit93] +FileName=..\..\x86\iVUops.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit94] +FileName=..\..\x86\recCOP2.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit95] +FileName=..\..\x86\ix86\ix86.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit96] +FileName=..\..\x86\ix86\ix86.h +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit97] +FileName=..\..\x86\ix86\ix86_3dnow.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit98] +FileName=..\..\x86\ix86\ix86_cpudetect.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit99] +FileName=..\..\x86\ix86\ix86_fpu.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit100] +FileName=..\..\x86\ix86\ix86_mmx.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit101] +FileName=..\..\x86\ix86\ix86_sse.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit102] +FileName=..\..\CDVD.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit103] +FileName=..\..\CDVD.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit104] +FileName=..\..\CDVDiso.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit105] +FileName=..\..\CDVDiso.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit106] +FileName=..\..\CDVDisodrv.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit107] +FileName=..\..\CDVDisodrv.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit108] +FileName=..\..\CDVDlib.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit109] +FileName=..\..\Common.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit110] +FileName=..\..\COP0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit111] +FileName=..\..\COP0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit112] +FileName=..\..\Counters.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit113] +FileName=..\..\Counters.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit114] +FileName=..\..\Decode_XA.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit115] +FileName=..\..\Decode_XA.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit116] +FileName=..\..\EEregs.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit117] +FileName=..\..\Elfheader.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit118] +FileName=..\..\Elfheader.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit119] +FileName=..\..\FiFo.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit120] +FileName=..\..\FPU.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit121] +FileName=..\..\GS.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit122] +FileName=..\..\GS.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit123] +FileName=..\..\Gte.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit124] +FileName=..\..\Gte.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit125] +FileName=..\..\Hw.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit126] +FileName=..\..\Hw.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit127] +FileName=..\..\Interpreter.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit128] +FileName=..\..\InterTables.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit129] +FileName=..\..\InterTables.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit130] +FileName=..\..\Mdec.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit131] +FileName=..\..\Mdec.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit132] +FileName=..\..\Memory.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit133] +FileName=..\..\Memory.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit134] +FileName=..\..\Misc.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit135] +FileName=..\..\Misc.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit136] +FileName=..\..\MMI.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit137] +FileName=..\..\Patch.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit138] +FileName=..\..\Patch.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit139] +FileName=..\..\Plugins.c +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit140] +FileName=..\..\Plugins.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit141] +FileName=..\..\PS2Edefs.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit142] +FileName=..\..\PS2Etypes.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit143] +FileName=..\..\PsxBios2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit144] +FileName=..\..\PsxBios.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit145] +FileName=..\..\PsxBios.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit146] +FileName=..\..\PsxCommon.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit147] +FileName=..\..\PsxCounters.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit148] +FileName=..\..\PsxCounters.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit149] +FileName=..\..\PsxDma.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit150] +FileName=..\..\PsxDma.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit151] +FileName=..\..\PsxGPU.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit152] +FileName=..\..\PsxGPU.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit153] +FileName=..\..\PsxHw.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit154] +FileName=..\..\PsxHw.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit155] +FileName=..\..\PsxInterpreter.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit156] +FileName=..\..\PsxMem.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit157] +FileName=..\..\PsxMem.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit158] +FileName=..\..\PsxSio2.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit159] +FileName=..\..\PsxSio2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit160] +FileName=..\..\R3000A.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit161] +FileName=..\..\R3000A.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit162] +FileName=..\..\R5900.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit163] +FileName=..\..\R5900.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit164] +FileName=..\..\Sif.c +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit165] +FileName=..\..\Sif.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit166] +FileName=..\..\Sifcmd.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit167] +FileName=..\..\Sio.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit168] +FileName=..\..\Sio.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit169] +FileName=..\..\SPR.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit170] +FileName=..\..\SPR.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit171] +FileName=..\..\Stats.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit172] +FileName=..\..\Stats.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit173] +FileName=..\..\System.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit174] +FileName=..\..\Vif.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit175] +FileName=..\..\Vif.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit176] +FileName=..\..\VifDma.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit177] +FileName=..\..\VifDma.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit178] +FileName=..\..\VU0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit179] +FileName=..\..\VU0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit180] +FileName=..\..\VU0micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit181] +FileName=..\..\VU1micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit182] +FileName=..\..\VU.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit183] +FileName=..\..\VUflags.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit184] +FileName=..\..\VUflags.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit185] +FileName=..\..\VUmicro.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit186] +FileName=..\..\VUops.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit187] +FileName=..\..\VUops.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit188] +FileName=..\..\Cache.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit189] +FileName=..\..\Cache.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit190] +FileName=..\..\CdRom.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit191] +FileName=..\..\CdRom.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit192] +FileName=..\Cdrom02.ico +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit193] +FileName=..\..\pcsxAbout.bmp +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit194] +FileName=..\..\RDebug\deci2.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit195] +FileName=..\..\RDebug\deci2.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit196] +FileName=..\..\RDebug\deci2_dbgp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit197] +FileName=..\..\RDebug\deci2_dbgp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit198] +FileName=..\..\RDebug\deci2_dcmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit199] +FileName=..\..\RDebug\deci2_dcmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit202] +FileName=..\..\RDebug\deci2_netmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit203] +FileName=..\..\RDebug\deci2_netmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit204] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit205] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit206] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit207] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit200] +FileName=..\..\RDebug\deci2_iloadp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit201] +FileName=..\..\RDebug\deci2_iloadp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/windows/mingw/pcsx2.layout b/windows/mingw/pcsx2.layout new file mode 100644 index 0000000000..eb0d940638 --- /dev/null +++ b/windows/mingw/pcsx2.layout @@ -0,0 +1,1424 @@ +[Editor_0] +CursorCol=1 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_1] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_4] +CursorCol=1 +CursorRow=95 +TopLine=54 +LeftChar=1 +Open=1 +Top=1 +[Editor_3] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_5] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_6] +CursorCol=2 +CursorRow=239 +TopLine=193 +LeftChar=1 +Open=0 +Top=0 +[Editor_8] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_9] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_7] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_10] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_11] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_12] +CursorCol=1 +CursorRow=19 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_13] +CursorCol=20 +CursorRow=172 +TopLine=132 +LeftChar=1 +Open=0 +Top=0 +[Editor_14] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_15] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_16] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_17] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_2] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_19] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_20] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_22] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_23] +CursorCol=1 +CursorRow=175 +TopLine=146 +LeftChar=1 +Open=0 +Top=0 +[Editor_24] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_25] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_26] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_21] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_27] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_28] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_29] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_31] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_30] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_32] +CursorCol=48 +CursorRow=360 +TopLine=315 +LeftChar=1 +Open=0 +Top=0 +[Editor_33] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_34] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_35] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_36] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_37] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_38] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_39] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_40] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_41] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_42] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_43] +CursorCol=8 +CursorRow=841 +TopLine=812 +LeftChar=1 +Open=0 +Top=0 +[Editor_44] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_45] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_46] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_47] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_48] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_49] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_50] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_51] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_52] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_53] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_54] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_55] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_56] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_57] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_58] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_59] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_60] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_61] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_62] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_63] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_64] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_65] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_66] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_67] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_68] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_69] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_70] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_71] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_72] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_73] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_74] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_75] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_76] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_77] +CursorCol=18 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_78] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_79] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_80] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_81] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_82] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_83] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_84] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_85] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_86] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_87] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_88] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_89] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_90] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_91] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_92] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_93] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_113] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_114] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_189] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_190] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_187] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_188] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_135] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_143] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_126] +CursorCol=1 +CursorRow=515 +TopLine=496 +LeftChar=1 +Open=0 +Top=0 +[Editor_127] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_128] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_133] +CursorCol=1 +CursorRow=684 +TopLine=643 +LeftChar=1 +Open=0 +Top=0 +[Editor_134] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_136] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_137] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_138] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_139] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_140] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_141] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_145] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_144] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_142] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_146] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_147] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_150] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_152] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_154] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_132] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_148] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_149] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_151] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_153] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_155] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_156] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_157] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_158] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_159] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_160] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_161] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_162] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_173] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_174] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_175] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_176] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_181] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_177] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_178] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_179] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_180] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_182] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_183] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_184] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_185] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_186] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_119] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_131] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_124] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_125] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_122] +CursorCol=17 +CursorRow=207 +TopLine=197 +LeftChar=1 +Open=0 +Top=0 +[Editor_123] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_129] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_130] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_163] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_164] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_166] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_167] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_109] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_110] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_192] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_170] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_168] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_169] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_165] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_111] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_112] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_101] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_102] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_103] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_104] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_105] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_106] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_107] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_115] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_116] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_117] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_118] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_120] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_121] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_171] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Focused=-1 +Order=-1 +[Editor_18] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_94] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_95] +Open=0 +Top=0 +[Editor_96] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_97] +Open=1 +Top=0 +CursorCol=28 +CursorRow=477 +TopLine=439 +LeftChar=1 +[Editor_98] +Open=0 +Top=0 +[Editor_99] +Open=0 +Top=0 +CursorCol=1 +CursorRow=337 +TopLine=296 +LeftChar=1 +[Editor_100] +Open=0 +Top=0 +[Editor_108] +Open=0 +Top=0 +CursorCol=3 +CursorRow=3 +TopLine=1 +LeftChar=1 +[Editor_172] +Open=0 +Top=0 +[Editor_191] +Open=0 +Top=0 +[Editor_193] +Open=0 +Top=0 +CursorCol=20 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_194] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_195] +Open=0 +Top=0 +CursorCol=1 +CursorRow=349 +TopLine=1 +LeftChar=1 +[Editor_196] +Open=0 +Top=0 +[Editor_197] +Open=0 +Top=0 +CursorCol=6 +CursorRow=42 +TopLine=37 +LeftChar=1 +[Editor_198] +Open=0 +Top=0 +CursorCol=6 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_199] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_200] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_201] +Open=0 +Top=0 +CursorCol=21 +CursorRow=133 +TopLine=89 +LeftChar=1 +[Editor_202] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_203] +Open=0 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_204] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_205] +Open=1 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_206] +Open=0 +Top=0 diff --git a/windows/mingw/pcsx2_private.h b/windows/mingw/pcsx2_private.h new file mode 100644 index 0000000000..38d384164e --- /dev/null +++ b/windows/mingw/pcsx2_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef PCSX2_PRIVATE_H +#define PCSX2_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*PCSX2_PRIVATE_H*/ diff --git a/windows/mingw/pcsx2_private.rc b/windows/mingw/pcsx2_private.rc new file mode 100644 index 0000000000..aea0afea38 --- /dev/null +++ b/windows/mingw/pcsx2_private.rc @@ -0,0 +1,5 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "../pcsx2.rc" + diff --git a/windows/pcsx2.rc b/windows/pcsx2.rc new file mode 100644 index 0000000000..8efabf2b1c --- /dev/null +++ b/windows/pcsx2.rc @@ -0,0 +1,1417 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Romanian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CMDLINE DIALOG 0, 0, 186, 82 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Program arguments" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,36,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,99,37,50,14 + CTEXT "Tip: If you don't know what to write\nleave it blank", + IDC_TIP,7,56,172,19,WS_BORDER + EDITTEXT IDC_CMDLINE,7,17,172,14,ES_AUTOHSCROLL + LTEXT "Fill in the command line arguments for opened program:", + IDC_TEXT,7,7,174,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CMDLINE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Romanian resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CP0REGS DIALOG 0, 0, 267, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP0 " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CP00,48,7,51,12,ES_READONLY + LTEXT "Index",-1,7,9,18,8 + EDITTEXT IDC_CP01,48,21,51,12,ES_READONLY + LTEXT "Random",-1,7,23,28,8 + EDITTEXT IDC_CP02,48,35,51,12,ES_READONLY + LTEXT "EntryLo0",-1,7,37,29,8 + EDITTEXT IDC_CP03,48,49,51,12,ES_READONLY + LTEXT "EntryLo1",-1,7,51,29,8 + EDITTEXT IDC_CP04,48,63,51,12,ES_READONLY + LTEXT "Context",-1,7,65,25,8 + EDITTEXT IDC_CP05,48,77,51,12,ES_READONLY + LTEXT "PageMask",-1,7,79,35,8 + EDITTEXT IDC_CP06,48,91,51,12,ES_READONLY + LTEXT "Wired",-1,7,93,20,8 + EDITTEXT IDC_CP07,48,105,51,12,ES_READONLY + EDITTEXT IDC_CP08,48,119,51,12,ES_READONLY + LTEXT "BadVAddr",-1,7,121,33,8 + EDITTEXT IDC_CP09,48,133,52,12,ES_READONLY + LTEXT "Count",-1,7,135,20,8 + EDITTEXT IDC_CP010,48,147,51,12,ES_READONLY + LTEXT "EntryHi",-1,7,149,24,8 + EDITTEXT IDC_CP011,48,161,52,12,ES_READONLY + LTEXT "Compare",-1,7,163,29,8 + EDITTEXT IDC_CP012,48,175,51,12,ES_READONLY + LTEXT "Status",-1,7,177,21,8 + EDITTEXT IDC_CP013,48,189,51,12,ES_READONLY + LTEXT "Cause",-1,7,191,21,8 + EDITTEXT IDC_CP014,48,203,51,12,ES_READONLY + LTEXT "EPC",-1,7,205,15,8 + EDITTEXT IDC_CP015,48,218,51,12,ES_READONLY + LTEXT "PRId",-1,7,219,17,8 + EDITTEXT IDC_CP016,191,7,51,12,ES_READONLY + LTEXT "Config",-1,145,9,21,8 + EDITTEXT IDC_CP017,191,21,51,12,ES_READONLY + EDITTEXT IDC_CP018,191,35,51,12,ES_READONLY + EDITTEXT IDC_CP019,191,49,51,12,ES_READONLY + EDITTEXT IDC_CP020,191,63,51,12,ES_READONLY + EDITTEXT IDC_CP021,191,77,51,12,ES_READONLY + EDITTEXT IDC_CP022,191,91,51,12,ES_READONLY + EDITTEXT IDC_CP023,191,105,51,12,ES_READONLY + EDITTEXT IDC_CP024,191,119,51,12,ES_READONLY + EDITTEXT IDC_CP025,191,133,51,12,ES_READONLY + EDITTEXT IDC_CP026,191,147,51,12,ES_READONLY + LTEXT "Debug",-1,147,122,22,8 + EDITTEXT IDC_CP027,191,161,51,12,ES_READONLY + LTEXT "Perf",-1,149,136,14,8 + EDITTEXT IDC_CP028,191,175,51,12,ES_READONLY + LTEXT "TagLo",-1,145,177,22,8 + EDITTEXT IDC_CP029,191,189,51,12,ES_READONLY + LTEXT "TagHi",-1,145,191,20,8 + EDITTEXT IDC_CP030,191,203,51,12,ES_READONLY + LTEXT "ErrorEPC",-1,145,205,30,8 + EDITTEXT IDC_CP031,191,218,51,12,ES_READONLY +END + +IDD_DEBUG DIALOGEX 0, 0, 281, 297 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Debugger" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM,7,28,198,235,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Close",IDC_DEBUG_CLOSE,223,249,50,14 + PUSHBUTTON "Step",IDC_DEBUG_STEP,223,36,50,14 + PUSHBUTTON "Skip",IDC_DEBUG_SKIP,223,54,50,14 + PUSHBUTTON "Go",IDC_DEBUG_GO,223,19,50,14 + PUSHBUTTON "Bkpt on Exec",IDC_DEBUG_BP_EXEC,223,129,50,14 + SCROLLBAR IDC_DEBUG_SCROLL,205,28,11,235,SBS_VERT + PUSHBUTTON "Jump to ADDR",IDC_DEBUG_JUMP,223,112,50,14 + PUSHBUTTON "Un/Set Log",IDC_DEBUG_LOG,223,71,50,14 + PUSHBUTTON "Bkpt on Count",IDC_DEBUG_BP_COUNT,223,145,50,14 + PUSHBUTTON "Dump code",IDC_DEBUG_DUMP,223,194,50,14 + PUSHBUTTON "Clear Bkpts",IDC_DEBUG_BP_CLEAR,223,162,50,14 + PUSHBUTTON "Dump memory",IDC_DEBUG_MEMORY,223,211,50,14 + PUSHBUTTON "Cpu ops",IDC_CPUOP,223,227,50,14 + PUSHBUTTON "Reset to PC",IDC_DEBUG_RESETTOPC,223,96,50,14 +END + +IDD_DUMP DIALOGEX 0, 0, 386, 96 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump code" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_DUMP_START,73,14,82,13 + EDITTEXT IDC_DUMP_END,73,29,82,13 + EDITTEXT IDC_DUMP_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,87,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,227,73,50,14 + LTEXT "Start PC Address:",IDC_STATIC,19,17,52,8 + LTEXT "End PC Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 + GROUPBOX "EE",IDC_STATIC,14,6,167,64 + EDITTEXT IDC_DUMP_STARTIOP,255,15,82,13 + EDITTEXT IDC_DUMP_ENDIOP,255,30,82,13 + EDITTEXT IDC_DUMP_FNAMEIOP,255,50,82,13,ES_AUTOHSCROLL + LTEXT "Start PC Address:",IDC_STATIC,201,18,52,8 + LTEXT "End PC Address:",IDC_STATIC,201,33,50,8 + LTEXT "Filename:",IDC_STATIC,201,54,31,8 + GROUPBOX "IOP",IDC_STATIC,195,7,167,63 +END + +IDD_GPREGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "R5900 Main registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_GPR0,22,7,166,12,ES_READONLY + LTEXT "R0",-1,7,9,10,8 + EDITTEXT IDC_GPR1,22,21,166,12,ES_READONLY + LTEXT "AT",-1,7,23,10,8 + EDITTEXT IDC_GPR2,22,35,166,12,ES_READONLY + LTEXT "V0",-1,7,37,10,8 + EDITTEXT IDC_GPR3,22,49,166,12,ES_READONLY + LTEXT "V1",-1,7,51,10,8 + EDITTEXT IDC_GPR4,22,63,166,12,ES_READONLY + LTEXT "A0",-1,7,65,10,8 + EDITTEXT IDC_GPR5,22,77,166,12,ES_READONLY + LTEXT "A1",-1,7,79,10,8 + EDITTEXT IDC_GPR6,22,91,166,12,ES_READONLY + LTEXT "A2",-1,7,93,10,8 + EDITTEXT IDC_GPR7,22,105,166,12,ES_READONLY + LTEXT "A3",-1,7,107,10,8 + EDITTEXT IDC_GPR8,22,119,166,12,ES_READONLY + LTEXT "T0",-1,7,121,10,8 + EDITTEXT IDC_GPR9,22,133,166,12,ES_READONLY + LTEXT "T1",-1,7,135,10,8 + EDITTEXT IDC_GPR10,22,147,166,12,ES_READONLY + LTEXT "T2",-1,7,149,10,8 + EDITTEXT IDC_GPR11,22,161,166,12,ES_READONLY + LTEXT "T3",-1,7,163,10,8 + EDITTEXT IDC_GPR12,22,175,166,12,ES_READONLY + LTEXT "T4",-1,7,177,10,8 + EDITTEXT IDC_GPR13,22,189,166,12,ES_READONLY + LTEXT "T5",-1,7,191,10,8 + EDITTEXT IDC_GPR14,22,203,166,12,ES_READONLY + LTEXT "T6",-1,7,205,10,8 + EDITTEXT IDC_GPR15,22,218,166,12,ES_READONLY + LTEXT "T7",-1,7,219,10,8 + EDITTEXT IDC_GPR16,214,7,165,12,ES_READONLY + LTEXT "S0",-1,196,10,10,8 + EDITTEXT IDC_GPR17,214,20,166,12,ES_READONLY + LTEXT "S1",-1,196,22,10,8 + EDITTEXT IDC_GPR18,214,35,166,12,ES_READONLY + LTEXT "S2",-1,196,36,10,8 + EDITTEXT IDC_GPR19,214,49,165,12,ES_READONLY + LTEXT "S3",-1,196,52,10,8 + EDITTEXT IDC_GPR20,214,63,165,12,ES_READONLY + LTEXT "S4",-1,196,66,10,8 + EDITTEXT IDC_GPR21,214,76,165,12,ES_READONLY + LTEXT "S5",-1,196,80,10,8 + EDITTEXT IDC_GPR22,214,91,165,12,ES_READONLY + LTEXT "S6",-1,196,94,10,8 + EDITTEXT IDC_GPR23,214,105,165,12,ES_READONLY + LTEXT "S7",-1,196,108,10,8 + EDITTEXT IDC_GPR24,214,119,165,12,ES_READONLY + LTEXT "T8",-1,196,121,10,8 + EDITTEXT IDC_GPR25,214,132,165,12,ES_READONLY + LTEXT "T9",-1,196,135,10,8 + EDITTEXT IDC_GPR26,214,147,165,12,ES_READONLY + LTEXT "K0",-1,196,149,10,8 + EDITTEXT IDC_GPR27,214,161,165,12,ES_READONLY + LTEXT "K1",-1,196,163,10,8 + EDITTEXT IDC_GPR28,214,175,165,12,ES_READONLY + LTEXT "GP",-1,196,178,11,8 + EDITTEXT IDC_GPR29,214,188,165,12,ES_READONLY + LTEXT "SP",-1,196,190,10,8 + EDITTEXT IDC_GPR30,214,203,165,12,ES_READONLY + LTEXT "S8",-1,196,205,10,8 + EDITTEXT IDC_GPR31,214,217,165,12,ES_READONLY + LTEXT "RA",-1,196,220,11,8 + EDITTEXT IDC_GPR_PC,20,260,57,12,ES_READONLY + LTEXT "PC",-1,7,263,10,8 + EDITTEXT IDC_GPR_HI,21,238,167,12,ES_READONLY + LTEXT "HI",-1,7,241,8,8 + LTEXT "LO",-1,196,241,10,8 + EDITTEXT IDC_GPR_LO,214,238,165,12,ES_READONLY +END + +IDD_JUMP DIALOG 0, 0, 175, 64 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Jump to specific address" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_JUMP_PC,73,14,82,13 + DEFPUSHBUTTON "OK",IDOK,25,43,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,42,50,14 + LTEXT "Enter new PC Address:",IDC_STATIC,3,18,70,8 +END + +IDD_MEMORY DIALOG 0, 0, 317, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Memory" +FONT 8, "Courier" +BEGIN + EDITTEXT IDC_MEMORY_ADDR,54,7,97,12 + PUSHBUTTON "Close",IDC_MEMORY_CLOSE,266,7,42,14 + LTEXT "Address:",IDC_STATIC,14,8,34,8 + LISTBOX IDC_MEMORY_DUMP,3,29,300,169,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_TABSTOP + SCROLLBAR IDC_MEM_SCROLL,303,29,9,172,SBS_VERT + GROUPBOX "Memory Patch",IDC_STATIC,3,204,307,57 + EDITTEXT IDC_ADDRESS_PATCH,124,220,97,12 + EDITTEXT IDC_DATA_PATCH,124,242,97,12 + LTEXT "Address",IDC_STATIC,84,222,40,8 + LTEXT "Data",IDC_STATIC,85,244,39,8 + PUSHBUTTON "Patch It",IDC_PATCH,238,230,64,16 + PUSHBUTTON "Raw dump",IDC_DUMPRAW,204,7,50,14 +END + +IDD_VU1INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1 Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU1_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU1_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU1_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU1_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU1_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU1_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU1_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU1_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU1_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU1_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU1_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU1_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU1_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU1_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU1_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU1_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU1_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU1_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU1_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU1_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU1_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU1_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU1_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU1_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU1_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU1_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU1_VI27,172,161,89,12,WS_DISABLED + LTEXT "P register",IDC_STATIC,124,108,30,8 + EDITTEXT IDC_VU1_VI28,172,175,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI29,172,189,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU1_VI31,172,218,89,12,WS_DISABLED + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU1_ACC,78,239,166,12,ES_READONLY +END + +IDD_VU0REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU0_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU0_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU0_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU0_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU0_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU0_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU0_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU0_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU0_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU0_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU0_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU0_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU0_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU0_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU0_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU0_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU0_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU0_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU0_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU0_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU0_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU0_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU0_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU0_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU0_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU0_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU0_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU0_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU0_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU0_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU0_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_CP1REGS DIALOG 0, 0, 357, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP1 Registers " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_FP0,29,7,89,12,WS_DISABLED + LTEXT "FP0",IDC_STATIC,7,9,14,8 + EDITTEXT IDC_FP1,29,21,89,12,WS_DISABLED + LTEXT "FP1",IDC_STATIC,7,23,14,8 + EDITTEXT IDC_FP2,29,35,89,12,WS_DISABLED + LTEXT "FP2",IDC_STATIC,7,37,14,8 + EDITTEXT IDC_FP3,29,49,89,12,WS_DISABLED + LTEXT "FP3",IDC_STATIC,7,51,14,8 + EDITTEXT IDC_FP4,29,63,89,12,WS_DISABLED + LTEXT "FP4",IDC_STATIC,7,65,14,8 + EDITTEXT IDC_FP5,29,77,89,12,WS_DISABLED + LTEXT "FP5",IDC_STATIC,7,79,14,8 + EDITTEXT IDC_FP6,29,91,89,12,WS_DISABLED + LTEXT "FP6",IDC_STATIC,7,93,14,8 + EDITTEXT IDC_FP7,29,105,89,12,WS_DISABLED + LTEXT "FP7",IDC_STATIC,7,107,14,8 + EDITTEXT IDC_FP8,29,119,89,12,WS_DISABLED + LTEXT "FP8",IDC_STATIC,7,121,14,8 + EDITTEXT IDC_FP9,29,133,89,12,WS_DISABLED + LTEXT "FP9",IDC_STATIC,7,135,14,8 + EDITTEXT IDC_FP10,29,147,89,12,WS_DISABLED + LTEXT "FP10",IDC_STATIC,7,149,18,8 + EDITTEXT IDC_FP11,29,161,89,12,WS_DISABLED + LTEXT "FP11",IDC_STATIC,7,163,18,8 + EDITTEXT IDC_FP12,29,175,89,12,WS_DISABLED + LTEXT "FP12",IDC_STATIC,7,177,18,8 + EDITTEXT IDC_FP13,29,189,89,12,WS_DISABLED + LTEXT "FP13",IDC_STATIC,7,191,18,8 + EDITTEXT IDC_FP14,29,203,89,12,WS_DISABLED + LTEXT "FP14",IDC_STATIC,7,205,18,8 + EDITTEXT IDC_FP15,29,218,89,12,WS_DISABLED + LTEXT "FP15",IDC_STATIC,7,219,18,8 + EDITTEXT IDC_FP16,145,7,89,12,WS_DISABLED + LTEXT "FP16",IDC_STATIC,123,9,18,8 + EDITTEXT IDC_FP17,145,21,89,12,WS_DISABLED + LTEXT "FP17",IDC_STATIC,123,23,18,8 + EDITTEXT IDC_FP18,145,35,89,12,WS_DISABLED + LTEXT "FP18",IDC_STATIC,123,37,18,8 + EDITTEXT IDC_FP19,145,49,89,12,WS_DISABLED + LTEXT "FP19",IDC_STATIC,123,51,18,8 + EDITTEXT IDC_FP20,145,63,89,12,WS_DISABLED + LTEXT "FP20",IDC_STATIC,123,65,18,8 + EDITTEXT IDC_FP21,145,77,89,12,WS_DISABLED + LTEXT "FP21",IDC_STATIC,123,79,18,8 + EDITTEXT IDC_FP22,145,91,89,12,WS_DISABLED + LTEXT "FP22",IDC_STATIC,123,93,18,8 + EDITTEXT IDC_FP23,145,105,89,12,WS_DISABLED + LTEXT "FP23",IDC_STATIC,123,107,18,8 + EDITTEXT IDC_FP24,145,119,89,12,WS_DISABLED + LTEXT "FP24",IDC_STATIC,123,121,18,8 + EDITTEXT IDC_FP25,145,133,89,12,WS_DISABLED + LTEXT "FP25",IDC_STATIC,123,135,18,8 + EDITTEXT IDC_FP26,145,147,89,12,WS_DISABLED + LTEXT "FP26",IDC_STATIC,123,149,18,8 + EDITTEXT IDC_FP27,145,161,89,12,WS_DISABLED + LTEXT "FP27",IDC_STATIC,123,163,18,8 + EDITTEXT IDC_FP28,145,175,89,12,WS_DISABLED + LTEXT "FP28",IDC_STATIC,123,177,18,8 + EDITTEXT IDC_FP29,145,189,89,12,WS_DISABLED + LTEXT "FP29",IDC_STATIC,123,191,18,8 + EDITTEXT IDC_FP30,145,203,89,12,WS_DISABLED + LTEXT "FP30",IDC_STATIC,123,205,18,8 + EDITTEXT IDC_FP31,145,218,89,12,WS_DISABLED + LTEXT "FP31",IDC_STATIC,123,219,18,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,244,8,1, + 223 + LTEXT "Implementation/Revision Reg",IDC_STATIC,253,9,94,8 + EDITTEXT IDC_FCR0,298,21,50,12,WS_DISABLED + LTEXT "FCR0",IDC_STATIC,253,23,19,8 + LTEXT "Control/Status Register",IDC_STATIC,253,37,74,8 + EDITTEXT IDC_FCR31,298,49,50,12,WS_DISABLED + LTEXT "FCR31",IDC_STATIC,253,51,23,8 + LTEXT "Accumulator",IDC_STATIC,256,68,43,14 + EDITTEXT IDC_FPU_ACC,299,68,49,12,ES_AUTOHSCROLL | WS_DISABLED +END + +IDD_VU0INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU0_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU0_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU0_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU0_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU0_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU0_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU0_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU0_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU0_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU0_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU0_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU0_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU0_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU0_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU0_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU0_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU0_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU0_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU0_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU0_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU0_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU0_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU0_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU0_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU0_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU0_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU0_VI27,172,161,89,12,WS_DISABLED + LTEXT "CMSAR0 reg",IDC_STATIC,123,163,42,8 + EDITTEXT IDC_VU0_VI28,172,175,89,12,WS_DISABLED + LTEXT "FBRST register",IDC_STATIC,123,177,49,8 + EDITTEXT IDC_VU0_VI29,172,189,89,12,WS_DISABLED + LTEXT "VPU-STAT reg",IDC_STATIC,123,191,48,8 + EDITTEXT IDC_VU0_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU0_VI31,172,218,89,12,WS_DISABLED + LTEXT "CMSAR1 reg",IDC_STATIC,123,219,42,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU0_ACC,78,239,166,12,ES_READONLY + LTEXT "P register",IDC_STATIC,124,108,30,8 +END + +IDD_VU1REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU1_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU1_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU1_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU1_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU1_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU1_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU1_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU1_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU1_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU1_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU1_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU1_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU1_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU1_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU1_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU1_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU1_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU1_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU1_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU1_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU1_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU1_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU1_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU1_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU1_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU1_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU1_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU1_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU1_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU1_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU1_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_RDEBUGPARAMS DIALOGEX 0, 0, 174, 58 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,37,50,14 + EDITTEXT IDC_PORT,127,7,40,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Accept connections on TCP/IP port:",IDC_STATIC,7,7,120, + 10 + CONTROL "Debug Bios",IDC_DEBUGBIOS,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | WS_TABSTOP,7,22,50,10 +END + +IDD_RDEBUG DIALOGEX 0, 0, 254, 271 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "E&xit",IDOK,199,251,48,14 + LISTBOX IDC_COMMUNICATION,7,7,240,211,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + PUSHBUTTON "&Clear",IDC_CLEAR,199,229,48,14 + EDITTEXT IDC_EEPC,74,229,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPPC,132,229,52,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "EE pc address:\t IOP pc address:",IDC_STATIC,77,219,113, + 9 + CONTROL "Debug EE",IDC_DEBUGEE,"Button",BS_AUTORADIOBUTTON,77, + 255,48,10 + CONTROL "Debug IOP",IDC_DEBUGIOP,"Button",BS_AUTORADIOBUTTON | + BS_LEFTTEXT,132,254,50,11 + EDITTEXT IDC_STOPAT,7,229,56,13,ES_AUTOHSCROLL + EDITTEXT IDC_STOPAFTER,7,252,56,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Break at (hex addr):",IDC_STATIC,7,219,67,8 + LTEXT "Break after (cycles):",IDC_STATIC,7,243,66,8 + EDITTEXT IDC_EECYCLE,74,241,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPCYCLE,132,241,52,12,ES_AUTOHSCROLL | ES_READONLY +END + +IDD_MCDCONF DIALOG 0, 0, 407, 197 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Memcard Manager" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,285,175,50,14 + PUSHBUTTON "Cancel",IDCANCEL,345,175,50,14 + EDITTEXT IDC_MCD1,10,155,160,14,ES_AUTOHSCROLL + EDITTEXT IDC_MCD2,235,155,160,14,ES_AUTOHSCROLL + PUSHBUTTON "Select Mcd",IDC_MCDSEL1,10,135,50,14 + PUSHBUTTON "Select Mcd",IDC_MCDSEL2,235,135,50,14 + GROUPBOX "Memory Card 2",IDC_FRAMEMCD2,230,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT1,65,135,50,14 + GROUPBOX "Memory Card 1",IDC_FRAMEMCD1,5,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT2,290,135,50,14 + CONTROL "List3",IDC_LIST1,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,15,160,110 + CONTROL "List3",IDC_LIST2,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,235,15,160,110 + PUSHBUTTON "Reload Mcd",IDC_RELOAD1,120,135,50,14 + PUSHBUTTON "Reload Mcd",IDC_RELOAD2,345,135,50,14 + PUSHBUTTON "-> Copy ->",IDC_COPYTO2,180,30,45,14 + PUSHBUTTON "<- Copy <-",IDC_COPYTO1,180,50,45,14 + PUSHBUTTON "Paste",IDC_PASTE,180,70,45,14 + PUSHBUTTON "<- Un/Delete",IDC_DELETE1,180,90,45,14 + PUSHBUTTON "Un/Delete ->",IDC_DELETE2,180,110,45,14 +END + +IDD_DUMPMEM DIALOG 0, 0, 175, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump memory" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_DUMPMEM_START,73,14,82,13 + EDITTEXT IDC_DUMPMEM_END,73,29,82,13 + EDITTEXT IDC_DUMPMEM_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,25,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,74,50,14 + LTEXT "Start Address:",IDC_STATIC,19,17,52,8 + LTEXT "End Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 +END + +IDD_DIALOGBAR DIALOGEX 0, 0, 330, 16 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "TODO: layout dialog bar",IDC_STATIC,126,4,77,8 +END + +IDD_IOPREGS DIALOGEX 0, 0, 417, 295 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "IOP Main Registers" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_IOPGPR0,22,20,166,12,ES_READONLY + LTEXT "R0",-1,7,23,10,8 + EDITTEXT IDC_IOPGPR1,22,34,166,12,ES_READONLY + LTEXT "AT",-1,7,36,10,8 + EDITTEXT IDC_IOPGPR2,22,49,166,12,ES_READONLY + LTEXT "V0",-1,7,50,10,8 + EDITTEXT IDC_IOPGPR3,22,63,166,12,ES_READONLY + LTEXT "V1",-1,7,65,10,8 + EDITTEXT IDC_IOPGPR4,22,76,166,12,ES_READONLY + LTEXT "A0",-1,7,79,10,8 + EDITTEXT IDC_IOPGPR5,22,90,166,12,ES_READONLY + LTEXT "A1",-1,7,92,10,8 + EDITTEXT IDC_IOPGPR6,22,105,166,12,ES_READONLY + LTEXT "A2",-1,7,106,10,8 + EDITTEXT IDC_IOPGPR7,22,119,166,12,ES_READONLY + LTEXT "A3",-1,7,121,10,8 + EDITTEXT IDC_IOPGPR8,22,132,166,12,ES_READONLY + LTEXT "T0",-1,7,135,10,8 + EDITTEXT IDC_IOPGPR9,22,146,166,12,ES_READONLY + LTEXT "T1",-1,7,148,10,8 + EDITTEXT IDC_IOPGPR10,22,161,166,12,ES_READONLY + LTEXT "T2",-1,7,162,10,8 + EDITTEXT IDC_IOPGPR11,22,175,166,12,ES_READONLY + LTEXT "T3",-1,7,177,10,8 + EDITTEXT IDC_IOPGPR12,22,188,166,12,ES_READONLY + LTEXT "T4",-1,7,191,10,8 + EDITTEXT IDC_IOPGPR13,22,202,166,12,ES_READONLY + LTEXT "T5",-1,7,204,10,8 + EDITTEXT IDC_IOPGPR14,22,217,166,12,ES_READONLY + LTEXT "T6",-1,7,218,10,8 + EDITTEXT IDC_IOPGPR15,22,231,166,12,ES_READONLY + LTEXT "T7",-1,7,233,10,8 + EDITTEXT IDC_IOPGPR16,214,20,165,12,ES_READONLY + LTEXT "S0",-1,196,23,10,8 + EDITTEXT IDC_IOPGPR17,214,34,166,12,ES_READONLY + LTEXT "S1",-1,196,36,10,8 + EDITTEXT IDC_IOPGPR18,214,49,166,12,ES_READONLY + LTEXT "S2",-1,196,50,10,8 + EDITTEXT IDC_IOPGPR19,214,63,165,12,ES_READONLY + LTEXT "S3",-1,196,66,10,8 + EDITTEXT IDC_IOPGPR20,214,76,165,12,ES_READONLY + LTEXT "S4",-1,196,79,10,8 + EDITTEXT IDC_IOPGPR21,214,90,165,12,ES_READONLY + LTEXT "S5",-1,196,94,10,8 + EDITTEXT IDC_IOPGPR22,214,105,165,12,ES_READONLY + LTEXT "S6",-1,196,108,10,8 + EDITTEXT IDC_IOPGPR23,214,119,165,12,ES_READONLY + LTEXT "S7",-1,196,122,10,8 + EDITTEXT IDC_IOPGPR24,214,132,165,12,ES_READONLY + LTEXT "T8",-1,196,135,10,8 + EDITTEXT IDC_IOPGPR25,214,146,165,12,ES_READONLY + LTEXT "T9",-1,196,148,10,8 + EDITTEXT IDC_IOPGPR26,214,161,165,12,ES_READONLY + LTEXT "K0",-1,196,162,10,8 + EDITTEXT IDC_IOPGPR27,214,175,165,12,ES_READONLY + LTEXT "K1",-1,196,177,10,8 + EDITTEXT IDC_IOPGPR28,214,188,165,12,ES_READONLY + LTEXT "GP",-1,196,191,11,8 + EDITTEXT IDC_IOPGPR29,214,202,165,12,ES_READONLY + LTEXT "SP",-1,196,204,10,8 + EDITTEXT IDC_IOPGPR30,214,217,165,12,ES_READONLY + LTEXT "S8",-1,196,218,10,8 + EDITTEXT IDC_IOPGPR31,214,231,165,12,ES_READONLY + LTEXT "RA",-1,196,234,11,8 + EDITTEXT IDC_IOPGPR_PC,20,272,57,12,ES_READONLY + LTEXT "PC",-1,7,276,10,8 + EDITTEXT IDC_IOPGPR_HI,21,252,167,12,ES_READONLY + LTEXT "HI",-1,7,255,8,8 + LTEXT "LO",-1,196,255,10,8 + EDITTEXT IDC_IOPGPR_LO,214,252,165,12,ES_READONLY +END + +IDD_USERNAME DIALOGEX 0, 0, 186, 79 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Enter User Name" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,58,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,58,50,14 + LTEXT "Pcsx2 needs to allocate physical memory in order to execute faster. Enter the windows username you wish this privilege to be enabled for.", + IDC_STATIC,7,7,172,25 + EDITTEXT IDC_USER_NAME,73,37,106,13,ES_AUTOHSCROLL + LTEXT "User Name:",IDC_STATIC,7,41,38,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DEBUG, DIALOG + BEGIN + BOTTOMMARGIN, 282 + END + + IDD_RDEBUGPARAMS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 167 + TOPMARGIN, 7 + BOTTOMMARGIN, 51 + END + + IDD_RDEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 247 + TOPMARGIN, 7 + BOTTOMMARGIN, 265 + END + + IDD_MCDCONF, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 240 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_DIALOGBAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 323 + TOPMARGIN, 7 + BOTTOMMARGIN, 9 + END + + IDD_IOPREGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 410 + TOPMARGIN, 7 + BOTTOMMARGIN, 284 + END + + IDD_USERNAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 72 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_PS2SILVER BITMAP "ps2_silver.bmp" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUT_DIALOG DIALOGEX 0, 0, 431, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_ACCEPTFILES +CAPTION "About" +FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,205,250,50,14 + CTEXT "PCSX2 \nVersion x.x",IDC_PCSX_ABOUT_TEXT,55,10,45,15,0, + WS_EX_TRANSPARENT + CTEXT "PCSX2 a PS2 Emulator...",IDC_PCSX_ABOUT_AUTHORS,9,36, + 135,92,0,WS_EX_TRANSPARENT + CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,88,158,311,77 + GROUPBOX "",IDC_STATIC,5,29,145,113 + GROUPBOX "",IDC_STATIC,77,148,333,91 + CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP,0,167,70,74 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + ABOUT_DIALOG, DIALOG + BEGIN + RIGHTMARGIN, 429 + BOTTOMMARGIN, 264 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +SPLASH_LOGO BITMAP "..\\pcsxAbout.bmp" +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 317, 244 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_LISTGS,10,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGGS,10,35,45,12 + PUSHBUTTON "Test...",IDC_TESTGS,60,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTGS,110,35,45,12 + COMBOBOX IDC_LISTSPU2,166,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGSPU2,165,35,45,12 + PUSHBUTTON "Test...",IDC_TESTSPU2,215,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTSPU2,265,35,43,12 + COMBOBOX IDC_LISTCDVD,10,105,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGCDVD,10,125,43,12 + PUSHBUTTON "Test...",IDC_TESTCDVD,60,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTCDVD,110,125,45,12 + COMBOBOX IDC_LISTBIOS,165,196,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,207,223,50,14 + PUSHBUTTON "Cancel",IDCANCEL,260,223,50,14 + RTEXT "Graphics",IDC_GRAPHICS,50,5,41,10,SS_CENTERIMAGE + RTEXT "Sound",IDC_SOUND,200,5,43,10,SS_CENTERIMAGE + RTEXT "Cdvdrom",IDC_CDVDROM,65,95,30,10,SS_CENTERIMAGE + RTEXT "Bios",IDC_BIOS,228,185,15,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD1,10,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD1,10,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD1,60,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD1,110,80,45,12 + RTEXT "Second Controller",IDC_SECONDCONTROLLER,205,50,58,10, + SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD2,166,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD2,165,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD2,215,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD2,265,80,45,12 + CTEXT "First Controller",IDC_FIRSTCONTROLLER,55,50,48,10, + SS_CENTERIMAGE + PUSHBUTTON "Set Bios Directory",IDC_BIOSDIR,90,223,65,14 + PUSHBUTTON "Set Plugins Directory",IDC_PLUGINSDIR,7,223,75,14 + COMBOBOX IDC_LISTDEV9,165,105,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGDEV9,165,125,43,12 + PUSHBUTTON "Test...",IDC_TESTDEV9,215,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTDEV9,265,125,45,12 + CTEXT "Dev9",IDC_DEV9,221,95,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTUSB,10,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGUSB,10,170,43,12 + PUSHBUTTON "Test...",IDC_TESTUSB,60,170,45,12 + PUSHBUTTON "About...",IDC_ABOUTUSB,110,170,45,12 + CTEXT "Usb",IDC_USB,66,140,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTFW,165,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGFW,165,169,43,12 + PUSHBUTTON "Test...",IDC_TESTFW,214,169,45,12 + PUSHBUTTON "About...",IDC_ABOUTFW,265,169,45,12 + LTEXT "FireWire",IDC_STATIC,227,141,39,8 +END + +IDD_BPEXEC DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Exec" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EXECBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Address:",IDC_STATIC,5,13,84,8 +END + +IDD_BPCNT DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Count" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CNTBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Count:",IDC_STATIC,5,13,77,8 +END + +IDD_CPUCONF DIALOGEX 0, 0, 181, 185 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "CPUconfig" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,58,164,50,14 + PUSHBUTTON "Cancel",IDCANCEL,112,164,50,14 + GROUPBOX "Misc Options",IDC_MISCOPTIONS,5,5,155,65 + CONTROL "Enable Console Output",IDC_PSXOUT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,20,89,10 + CONTROL "Enable Patches",IDC_PATCH,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,35,88,12 + GROUPBOX "CPU Options",IDC_RECOPTIONS,5,70,157,65 + COMBOBOX IDC_THPRIORITY,90,50,63,55,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Process Priority",IDC_STATIC,20,50,55,12,SS_CENTERIMAGE + COMBOBOX IDC_CPUOPTION,32,89,106,55,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP +END + +IDD_ADVANCED DIALOGEX 0, 0, 177, 69 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Advanced" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,47,50,14 + PUSHBUTTON "Cancel",IDCANCEL,121,47,50,14 + CONTROL "Enable Reg Caching",IDC_REGCACHING,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,15,81,10 + GROUPBOX "",IDC_STATIC,2,7,168,38 + PUSHBUTTON "Reset",IDC_ADVRESET,5,47,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 310 + TOPMARGIN, 7 + BOTTOMMARGIN, 237 + HORZGUIDE, 169 + END + + IDD_BPEXEC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 6 + BOTTOMMARGIN, 54 + END + + IDD_BPCNT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + IDD_CPUCONF, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 174 + VERTGUIDE, 162 + TOPMARGIN, 7 + BOTTOMMARGIN, 178 + HORZGUIDE, 34 + HORZGUIDE, 46 + END + + IDD_ADVANCED, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "Cdrom02.ico" +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Greek resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ELL) +#ifdef _WIN32 +LANGUAGE LANG_GREEK, SUBLANG_DEFAULT +#pragma code_page(1253) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PATCHBROWSER DIALOGEX 0, 0, 487, 282 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | + WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Patches Browser" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "New Patch",IDC_NEWPATCH,112,257,60,14 + EDITTEXT IDC_PATCHTEXT,113,95,354,153,ES_MULTILINE | + ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL + PUSHBUTTON "Save Patch",IDC_SAVEPATCH,186,257,60,14,WS_DISABLED + PUSHBUTTON "Refresh List",IDC_REFRESHPATCHLIST,21,257,60,14 + LISTBOX IDC_PATCHCRCLIST,19,95,69,153,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_PATCHNAMELIST,17,34,452,50,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Search game name patch:",IDC_GAMENAMESEARCH,17,16,101,9 + EDITTEXT IDC_SEARCHPATCHTEXT,109,14,295,12,ES_AUTOHSCROLL + PUSHBUTTON "Exit",IDC_EXITPB,411,257,59,14 +END + +IDD_LOGGING DIALOGEX 0, 0, 263, 177 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Logging" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,206,156,50,14 + CONTROL "Cpu log",IDC_CPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,5,53,10 + CONTROL "COP0 log",IDC_COP0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,20,59,10 + CONTROL "FPU log",IDC_FPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,35,55,10 + CONTROL "MMI log",IDC_MMILOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,50,55,10 + CONTROL "VUO log",IDC_VU0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,65,56,10 + CONTROL "Bios log",IDC_BIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,80,54,10 + CONTROL "DMA log",IDC_DMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,95,57,10 + CONTROL "HW log",IDC_HWLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 5,110,53,10 + CONTROL "Unknown Memory log",IDC_MEMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,5,84,10 + CONTROL "Elf log",IDC_ELFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,20,35,10 + CONTROL "VIF log",IDC_VIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,35,38,10 + CONTROL "Scratch pad log",IDC_SPRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,50,66,10 + CONTROL "Gif log",IDC_GIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,65,49,10 + CONTROL "SIF log",IDC_SIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,80,51,10 + GROUPBOX "IOP",IDC_STATIC,161,7,95,127 + CONTROL "IOP cpu log",IDC_IOPLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,15,67,10 + CONTROL "HW log",IDC_IOPHWLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,30,53,10 + CONTROL "Bios log",IDC_IOPBIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,45,41,10 + CONTROL "Unknown Memory log",IDC_IOPMEMLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,165,60,85,10 + CONTROL "IPU log",IDC_IPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,95,39,10 + CONTROL "DMA log",IDC_IOPDMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,75,67,10 + CONTROL "PAD log",IDC_IOPPADLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,90,53,10 + CONTROL "CDR log",IDC_IOPCDRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,104,43,10 + CONTROL "VUMicro log",IDC_VUMICROLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,110,55,10 + CONTROL "RPC services log",IDC_RPCSERVICES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,5,125,67,10 + CONTROL "Log to STDOUT",IDC_STDOUTPUTLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,75,125,68,10 + CONTROL "Log",IDC_LOGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5, + 140,28,10 + CONTROL "Symbols log",IDC_SYMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,140,53,10 + CONTROL "Counters log",IDC_IOPCNTLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,118,55,10 +END + +IDD_IOP_DEBUG DIALOGEX 0, 0, 358, 107 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Debug" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM_IOP,7,7,330,92,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + SCROLLBAR IDC_DEBUG_SCROLL_IOP,340,7,11,93,SBS_VERT +END + +IDD_CPUDLG DIALOGEX 0, 0, 253, 289 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,268,50,14 + PUSHBUTTON "Cancel",IDCANCEL,82,268,50,14,NOT WS_TABSTOP + LTEXT "CPU vendor ",IDC_VENDORNAME,12,24,54,12 + GROUPBOX "",IDC_STATIC,7,12,239,90 + LTEXT "Family",IDC_FAMILYNAME,12,42,54,12 + LTEXT "Cpu Speed",IDC_CPUSPEEDNAME,12,60,54,12 + LTEXT "Features",IDC_FEATURESNAME,12,78,54,12 + LTEXT "",IDC_VENDORINPUT,72,24,162,12 + LTEXT "",IDC_FAMILYINPUT,72,42,162,12 + LTEXT "",IDC_FEATURESINPUT,71,82,162,12 + LTEXT "",IDC_CPUSPEEDINPUT,72,60,162,12 + CONTROL "Dual Core Mode (DC) - only valid with MTGS", + IDC_CPU_MULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 232,214,13 + CONTROL "Multi threaded GS mode (MTGS)\n (faster on dual core/HT procs, requires pcsx2 restart)", + IDC_CPU_GSMULTI,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,7,210,208,18 + CONTROL "Frame Limit (FL) - limits speed to normal speeds", + IDC_CPU_FRAMELIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 7,248,188,13 + CONTROL "VU1rec - enable recompiler for VU1 unit",IDC_CPU_VU1REC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,154,142,18 + CONTROL "VU0rec - enable recompiler for VU0 unit",IDC_CPU_VU0REC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,170,193,18 + CONTROL "EERec - EE/IOP recompiler (need MMX/SSE)", + IDC_CPU_EEREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 110,161,18 + CONTROL "Safe Floating Point (higher compat, removes spiky polys)", + IDC_CPU_FORCEABS,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,7,125,239,18 + GROUPBOX "VU Recompilers - All options are set by default", + IDC_STATIC,7,144,189,46 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_LOGGING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 256 + TOPMARGIN, 7 + BOTTOMMARGIN, 170 + END + + IDD_IOP_DEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 351 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_CPUDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 246 + VERTGUIDE, 39 + VERTGUIDE, 59 + TOPMARGIN, 7 + BOTTOMMARGIN, 282 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Greek resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/windows/ps2_silver.bmp b/windows/ps2_silver.bmp new file mode 100644 index 0000000000..cb58820cdf Binary files /dev/null and b/windows/ps2_silver.bmp differ diff --git a/windows/pthreadVC2.lib b/windows/pthreadVC2.lib new file mode 100644 index 0000000000..b447a8b71e Binary files /dev/null and b/windows/pthreadVC2.lib differ diff --git a/windows/resource.h b/windows/resource.h new file mode 100644 index 0000000000..296c3d67cd --- /dev/null +++ b/windows/resource.h @@ -0,0 +1,640 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pcsx2.rc +// +#define IDR_MENU 101 +#define IDD_CONFIG 101 +#define IDD_MCDCONF 102 +#define IDD_BPEXEC 103 +#define ABOUT_DIALOG 104 +#define IDD_BPCNT 105 +#define IDD_CPUCONF 106 +#define IDD_DEBUG 108 +#define IDI_ICON 108 +#define IDD_MEMORY 110 +#define IDD_VU0REGS 111 +#define IDD_JUMP 112 +#define SPLASH_LOGO 113 +#define IDD_VU0INTEGER 113 +#define IDD_GPREGS 114 +#define IDD_CP0REGS 115 +#define IDD_CP1REGS 116 +#define IDD_VU1INTEGER 117 +#define IDD_VU1REGS 118 +#define IDD_LOGGING 119 +#define IDD_CMDLINE 120 +#define IDD_RDEBUGPARAMS 121 +#define ID_DEBUG_REMOTEDEBUGGING 122 +#define IDD_RDEBUG 123 +#define IDD_DIALOGBAR 124 +#define IDD_IOP_DEBUG 125 +#define IDD_CPUDLG 126 +#define IDD_ADVANCED 127 +#define IDD_IOPREGS 128 +#define IDD_USERNAME 129 +#define IDB_PS2SILVER 132 +#define IDD_DUMP 136 +#define IDD_DUMPMEM 137 +#define IDD_PATCHBROWSER 138 +#define IDC_MEM_SCROLL 1001 +#define IDC_EXECBP 1001 +#define IDC_CNTBP 1002 +#define IDC_MCD2 1004 +#define IDC_VU0_VF00 1005 +#define IDC_MCD1 1005 +#define IDC_VU0_VF01 1006 +#define IDC_MCDSEL1 1006 +#define IDC_VU0_VF02 1007 +#define IDC_MCDSEL2 1007 +#define IDC_VU0_VF03 1008 +#define IDC_VU0_VF04 1009 +#define IDC_DEBUG_DISASM 1010 +#define IDC_VU0_VF05 1010 +#define IDC_VU0_VF06 1011 +#define IDC_VU0_VF07 1012 +#define IDC_VU0_VF08 1013 +#define IDC_PCSX_ABOUT_TEXT 1014 +#define IDC_PSXOUT 1014 +#define IDC_VU0_VF09 1014 +#define IDC_CPU 1015 +#define IDC_VU0_VF10 1015 +#define IDC_VSYNCHACK 1016 +#define IDC_VU0_VF11 1016 +#define IDC_VU0_VF12 1017 +#define IDC_VU0_VF13 1018 +#define IDC_VU0_VF14 1019 +#define IDC_CP07 1020 +#define IDC_VU0_VF15 1020 +#define IDC_VU0_VF16 1021 +#define IDC_VU0_VF17 1022 +#define IDC_VU0_VF18 1023 +#define IDC_VU0_VF19 1024 +#define IDC_VU0_VF20 1025 +#define IDC_VU0_VF21 1026 +#define IDC_VU0_VF22 1027 +#define IDC_VU0_VF23 1028 +#define IDC_DEBUG_CLOSE 1029 +#define IDC_VU0_VF24 1029 +#define IDC_DEBUG_STEP 1030 +#define IDC_VU0_VF25 1030 +#define IDC_DEBUG_SKIP 1031 +#define IDC_VU0_VF26 1031 +#define IDC_DEBUG_GO 1032 +#define IDC_VU0_VF27 1032 +#define IDC_DEBUG_BP_EXEC 1033 +#define IDC_VU0_VF28 1033 +#define IDC_CP021 1034 +#define IDC_DEBUG_SCROLL 1034 +#define IDC_VU0_VF29 1034 +#define IDC_CP022 1035 +#define IDC_DEBUG_RESETTOPC 1035 +#define IDC_VU0_VF30 1035 +#define IDC_CP023 1036 +#define IDC_FPU_ACC 1036 +#define IDC_DEBUG_JUMP 1036 +#define IDC_MEMORY_CLOSE 1036 +#define IDC_VU0_VF31 1036 +#define IDC_CP024 1037 +#define IDC_DEBUG_BREAK 1037 +#define IDC_MEMORY_ADDR 1037 +#define IDC_DEBUG_LOG 1037 +#define IDC_CP025 1038 +#define IDC_MEMORY_DUMP 1038 +#define IDC_DEBUG_BP_COUNT 1038 +#define IDC_VU0_VI00 1038 +#define IDC_DEBUG_L1 1039 +#define IDC_VU0_VI01 1039 +#define IDC_ADDRESS_PATCH 1039 +#define IDC_DEBUG_L2 1040 +#define IDC_VU0_VI02 1040 +#define IDC_DATA_PATCH 1040 +#define IDC_DEBUG_L3 1041 +#define IDC_VU0_VI03 1041 +#define IDC_FRAMEMCD1 1041 +#define IDC_DEBUG_L4 1042 +#define IDC_VU0_VI04 1042 +#define IDC_FRAMEMCD2 1042 +#define IDC_DEBUG_L5 1043 +#define IDC_VU0_VI05 1043 +#define IDC_CP031 1044 +#define IDC_DEBUG_L6 1044 +#define IDC_VU0_VI06 1044 +#define IDC_DEBUG_L7 1045 +#define IDC_VU0_VI07 1045 +#define IDC_DEBUG_L8 1046 +#define IDC_VU0_VI08 1046 +#define IDC_DEBUG_L9 1047 +#define IDC_GPR0 1047 +#define IDC_VU0_VI09 1047 +#define IDC_DEBUG_L10 1048 +#define IDC_GPR1 1048 +#define IDC_VU0_VI10 1048 +#define IDC_DEBUG_L11 1049 +#define IDC_GPR2 1049 +#define IDC_VU0_VI11 1049 +#define IDC_DEBUG_L12 1050 +#define IDC_GPR3 1050 +#define IDC_VU0_VI12 1050 +#define IDC_DEBUG_L13 1051 +#define IDC_GPR4 1051 +#define IDC_VU0_VI13 1051 +#define IDC_DEBUG_L14 1052 +#define IDC_GPR5 1052 +#define IDC_LISTGS 1052 +#define IDC_VU0_VI14 1052 +#define IDC_DEBUG_L15 1053 +#define IDC_GPR6 1053 +#define IDC_LISTSPU 1053 +#define IDC_VU0_VI15 1053 +#define IDC_LISTSPU2 1053 +#define IDC_DEBUG_L16 1054 +#define IDC_GPR7 1054 +#define IDC_LISTCDR 1054 +#define IDC_VU0_VI16 1054 +#define IDC_LISTCDVD 1054 +#define IDC_DEBUG_L17 1055 +#define IDC_GPR8 1055 +#define IDC_LISTBIOS 1055 +#define IDC_VU0_VI17 1055 +#define IDC_DEBUG_L18 1056 +#define IDC_GPR9 1056 +#define IDC_CONFIGGS 1056 +#define IDC_VU0_VI18 1056 +#define IDC_DEBUG_L19 1057 +#define IDC_GPR10 1057 +#define IDC_TESTGS 1057 +#define IDC_VU0_VI19 1057 +#define IDC_DEBUG_L20 1058 +#define IDC_ABOUTGS 1058 +#define IDC_VU0_VI20 1058 +#define IDC_DEBUG_L21 1059 +#define IDC_CONFIGSPU 1059 +#define IDC_VU0_VI21 1059 +#define IDC_CONFIGSPU2 1059 +#define IDC_DEBUG_L22 1060 +#define IDC_TESTSPU 1060 +#define IDC_VU0_VI22 1060 +#define IDC_TESTSPU2 1060 +#define IDC_DEBUG_L23 1061 +#define IDC_ABOUTSPU 1061 +#define IDC_VU0_VI23 1061 +#define IDC_ABOUTSPU2 1061 +#define IDC_DEBUG_L24 1062 +#define IDC_CONFIGCDR 1062 +#define IDC_VU0_VI24 1062 +#define IDC_CONFIGCDVD 1062 +#define IDC_DEBUG_L25 1063 +#define IDC_GPR11 1063 +#define IDC_TESTCDR 1063 +#define IDC_VU0_VI25 1063 +#define IDC_TESTCDVD 1063 +#define IDC_DEBUG_L26 1064 +#define IDC_ABOUTCDR 1064 +#define IDC_VU0_VI26 1064 +#define IDC_ABOUTCDVD 1064 +#define IDC_DEBUG_L27 1065 +#define IDC_VU0_VI27 1065 +#define IDC_LISTDEV9 1065 +#define IDC_DEBUG_L28 1066 +#define IDC_LISTPAD 1066 +#define IDC_LISTPAD1 1066 +#define IDC_VU0_VI28 1066 +#define IDC_DEBUG_L29 1067 +#define IDC_CONFIGPAD 1067 +#define IDC_CONFIGPAD1 1067 +#define IDC_VU0_VI29 1067 +#define IDC_DEBUG_R1 1068 +#define IDC_GPR12 1068 +#define IDC_TESTPAD 1068 +#define IDC_TESTPAD1 1068 +#define IDC_VU0_VI30 1068 +#define IDC_DEBUG_R2 1069 +#define IDC_GPR13 1069 +#define IDC_ABOUTPAD 1069 +#define IDC_ABOUTPAD1 1069 +#define IDC_VU0_VI31 1069 +#define IDC_DEBUG_R3 1070 +#define IDC_GPR14 1070 +#define IDC_LISTPAD2 1070 +#define IDC_VU0_ACC 1070 +#define IDC_DEBUG_R4 1071 +#define IDC_GPR15 1071 +#define IDC_CONFIGPAD2 1071 +#define IDC_VU1_VF00 1071 +#define IDC_DEBUG_R5 1072 +#define IDC_GPR16 1072 +#define IDC_TESTPAD2 1072 +#define IDC_VU1_VF01 1072 +#define IDC_DEBUG_R6 1073 +#define IDC_GPR17 1073 +#define IDC_ABOUTPAD2 1073 +#define IDC_VU1_VF02 1073 +#define IDC_DEBUG_R7 1074 +#define IDC_GPR18 1074 +#define IDC_VU1_VF03 1074 +#define IDC_CONFIGDEV9 1074 +#define IDC_DEBUG_R8 1075 +#define IDC_GPR19 1075 +#define IDC_VU1_VF04 1075 +#define IDC_TESTDEV9 1075 +#define IDC_DEBUG_R9 1076 +#define IDC_GPR20 1076 +#define IDC_VU1_VF05 1076 +#define IDC_ABOUTDEV9 1076 +#define IDC_DEBUG_R10 1077 +#define IDC_GPR21 1077 +#define IDC_VU1_VF06 1077 +#define IDC_LISTUSB 1077 +#define IDC_DEBUG_R11 1078 +#define IDC_GPR22 1078 +#define IDC_VU1_VF07 1078 +#define IDC_CONFIGUSB 1078 +#define IDC_DEBUG_R12 1079 +#define IDC_GPR23 1079 +#define IDC_VU1_VF08 1079 +#define IDC_TESTUSB 1079 +#define IDC_DEBUG_R13 1080 +#define IDC_GPR24 1080 +#define IDC_VU1_VF09 1080 +#define IDC_ABOUTUSB 1080 +#define IDC_DEBUG_R14 1081 +#define IDC_GPR25 1081 +#define IDC_VU1_VF10 1081 +#define IDC_LISTFW 1081 +#define IDC_DEBUG_R15 1082 +#define IDC_GPR26 1082 +#define IDC_VU1_VF11 1082 +#define IDC_CONFIGFW 1082 +#define IDC_DEBUG_R16 1083 +#define IDC_GPR27 1083 +#define IDC_VU1_VF12 1083 +#define IDC_TESTFW 1083 +#define IDC_DEBUG_R17 1084 +#define IDC_GPR28 1084 +#define IDC_VU1_VF13 1084 +#define IDC_ABOUTFW 1084 +#define IDC_DEBUG_R18 1085 +#define IDC_GPR29 1085 +#define IDC_VU1_VF14 1085 +#define IDC_DEBUG_R19 1086 +#define IDC_GPR30 1086 +#define IDC_VU1_VF15 1086 +#define IDC_DEBUG_R20 1087 +#define IDC_GPR31 1087 +#define IDC_VU1_VF16 1087 +#define IDC_DEBUG_R21 1088 +#define IDC_VU1_VF17 1088 +#define IDC_DEBUG_R22 1089 +#define IDC_GPR_PC 1089 +#define IDC_VU1_VF18 1089 +#define IDC_DEBUG_R23 1090 +#define IDC_VU1_VF19 1090 +#define IDC_DEBUG_R24 1091 +#define IDC_GPR_HI 1091 +#define IDC_VU1_VF20 1091 +#define IDC_DEBUG_R25 1092 +#define IDC_GPR_LO 1092 +#define IDC_VU1_VF21 1092 +#define IDC_CP00 1093 +#define IDC_DEBUG_R26 1093 +#define IDC_VU1_VF22 1093 +#define IDC_CP01 1094 +#define IDC_DEBUG_R27 1094 +#define IDC_VU1_VF23 1094 +#define IDC_CP02 1095 +#define IDC_DEBUG_R28 1095 +#define IDC_VU1_VF24 1095 +#define IDC_CP03 1096 +#define IDC_DEBUG_R29 1096 +#define IDC_VU1_VF25 1096 +#define IDC_CP04 1097 +#define IDC_DEBUG_DUMP 1097 +#define IDC_JUMP_PC 1097 +#define IDC_VU1_VF26 1097 +#define IDC_CP05 1098 +#define IDC_DEBUG_DUMPRAW 1098 +#define IDC_DUMP_END 1098 +#define IDC_VU1_VF27 1098 +#define IDC_DEBUG_LOGGING 1098 +#define IDC_DEBUG_MEMORY 1098 +#define IDC_CP06 1099 +#define IDC_DUMP_FNAME 1099 +#define IDC_DEBUG_BP_CLEAR 1099 +#define IDC_VU1_VF28 1099 +#define IDC_CP08 1100 +#define IDC_VU1_VF29 1100 +#define IDC_DUMP_ENDIOP 1100 +#define IDC_CP09 1101 +#define IDC_VU1_VF30 1101 +#define IDC_DUMP_FNAMEIOP 1101 +#define IDC_CP010 1102 +#define IDC_VU1_VF31 1102 +#define IDC_CP011 1103 +#define IDC_VU1_VI00 1103 +#define IDC_CP012 1104 +#define IDC_VU1_VI01 1104 +#define IDC_CP013 1105 +#define IDC_VU1_VI02 1105 +#define IDC_CP014 1106 +#define IDC_VU1_VI03 1106 +#define IDC_CP015 1107 +#define IDC_VU1_VI04 1107 +#define IDC_CP016 1108 +#define IDC_VU1_VI05 1108 +#define IDC_CP017 1109 +#define IDC_VU1_VI06 1109 +#define IDC_CP018 1110 +#define IDC_VU1_VI07 1110 +#define IDC_CP019 1111 +#define IDC_VU1_VI08 1111 +#define IDC_CP020 1112 +#define IDC_VU1_VI09 1112 +#define IDC_CP026 1113 +#define IDC_VU1_VI10 1113 +#define IDC_CP027 1114 +#define IDC_VU1_VI11 1114 +#define IDC_CP028 1115 +#define IDC_VU1_VI12 1115 +#define IDC_CP029 1116 +#define IDC_VU1_VI13 1116 +#define IDC_CP030 1117 +#define IDC_VU1_VI14 1117 +#define IDC_FP0 1118 +#define IDC_VU1_VI15 1118 +#define IDC_FP1 1119 +#define IDC_VU1_VI16 1119 +#define IDC_FP2 1120 +#define IDC_VU1_VI17 1120 +#define IDC_FP3 1121 +#define IDC_VU1_VI18 1121 +#define IDC_FP4 1122 +#define IDC_VU1_VI19 1122 +#define IDC_FP5 1123 +#define IDC_VU1_VI20 1123 +#define IDC_FP6 1124 +#define IDC_VU1_VI21 1124 +#define IDC_FP7 1125 +#define IDC_VU1_VI22 1125 +#define IDC_FP8 1126 +#define IDC_VU1_VI23 1126 +#define IDC_FP9 1127 +#define IDC_VU1_VI24 1127 +#define IDC_FP10 1128 +#define IDC_VU1_VI25 1128 +#define IDC_FP11 1129 +#define IDC_VU1_VI26 1129 +#define IDC_FP12 1130 +#define IDC_VU1_VI27 1130 +#define IDC_FP13 1131 +#define IDC_VU1_VI28 1131 +#define IDC_FP14 1132 +#define IDC_VU1_VI29 1132 +#define IDC_FP15 1133 +#define IDC_VU1_VI30 1133 +#define IDC_FP16 1134 +#define IDC_VU1_VI31 1134 +#define IDC_FP17 1135 +#define IDC_VU1_ACC 1135 +#define IDC_FP18 1136 +#define IDC_FP19 1137 +#define IDC_FP20 1138 +#define IDC_FP21 1139 +#define IDC_FP22 1140 +#define IDC_FP23 1141 +#define IDC_FP24 1142 +#define IDC_FP25 1143 +#define IDC_FP26 1144 +#define IDC_FP27 1145 +#define IDC_FP28 1146 +#define IDC_FP29 1147 +#define IDC_FP30 1148 +#define IDC_FP31 1149 +#define IDC_FCR0 1150 +#define IDC_FCR31 1151 +#define IDC_CMDLINE 1155 +#define IDC_PORT 1157 +#define IDC_COMMUNICATION 1158 +#define IDC_CLEAR 1160 +#define IDC_DEBUGBIOS 1161 +#define IDC_EEPC 1162 +#define IDC_IOPPC 1163 +#define IDC_PCSX_ABOUT_GREETS 1163 +#define IDC_PCSX_ABOUT_AUTHORS 1164 +#define IDC_EECYCLE 1164 +#define IDC_GRAPHICS 1165 +#define IDC_IOPCYCLE 1165 +#define IDC_SOUND 1166 +#define IDC_FIRSTCONTROLLER 1167 +#define IDC_SECONDCONTROLLER 1168 +#define IDC_CDVDROM 1169 +#define IDC_BIOS 1170 +#define IDC_MISCOPTIONS 1171 +#define IDC_DEV9 1171 +#define IDC_DUMP_START 1172 +#define IDC_TIP 1172 +#define IDC_USB 1172 +#define IDC_TEXT 1173 +#define IDC_DUMP_STARTIOP 1173 +#define IDC_CPUOP 1175 +#define IDC_DEBUGEE 1176 +#define IDC_DEBUGIOP 1177 +#define IDC_STOPAT 1178 +#define IDC_STOPAFTER 1179 +#define IDC_PATCH 1180 +#define IDC_REGCACHE 1181 +#define IDC_RECOPTIONS 1182 +#define IDC_PADHACK 1183 +#define IDC_VUREC 1184 +#define IDC_LOGS 1186 +#define IDDELREG 1187 +#define IDC_TAB_DEBUG 1188 +#define IDC_DUMPMEM_FNAME 1188 +#define IDC_DUMPMEM_END 1189 +#define IDC_DUMPMEM_START 1190 +#define IDC_DUMPRAW 1191 +#define IDC_DEBUG_DISASM_IOP 1193 +#define IDC_DEBUG_SCROLL_IOP 1194 +#define IDC_THPRIORITY 1195 +#define IDC_EXITPB 1196 +#define IDC_CPUOPTION 1196 +#define IDC_VENDORNAME 1197 +#define IDC_FAMILYNAME 1198 +#define IDC_CPUSPEEDNAME 1199 +#define IDC_FEATURESNAME 1200 +#define IDC_VENDORINPUT 1201 +#define IDC_FAMILYINPUT 1202 +#define IDC_CPUSPEEDINPUT 1203 +#define IDC_FEATURESINPUT 1204 +#define IDC_RADIOINTEPRETER 1205 +#define IDC_RADIORECOMPILER 1206 +#define IDC_RADIORECOMPILERVU 1207 +#define IDC_REGCACHING 1208 +#define IDC_INTERLACEHACK 1210 +#define IDC_SAFECOUNTERS 1211 +#define IDC_IOPCLK 1213 +#define IDC_ADVRESET 1214 +#define IDC_FASTIOPCLK 1215 +#define IDC_CHECK2 1217 +#define IDC_SPU2HACK 1218 +#define IDC_VSYNCRATE 1219 +#define IDC_IOPGPR0 1220 +#define IDC_IOPGPR1 1221 +#define IDC_IOPGPR2 1222 +#define IDC_IOPGPR16 1223 +#define IDC_IOPGPR17 1224 +#define IDC_IOPGPR18 1225 +#define IDC_IOPGPR19 1226 +#define IDC_IOPGPR20 1227 +#define IDC_IOPGPR21 1228 +#define IDC_IOPGPR22 1229 +#define IDC_IOPGPR23 1230 +#define IDC_IOPGPR24 1231 +#define IDC_IOPGPR25 1232 +#define IDC_IOPGPR26 1233 +#define IDC_IOPGPR27 1234 +#define IDC_IOPGPR28 1235 +#define IDC_IOPGPR29 1236 +#define IDC_IOPGPR30 1237 +#define IDC_IOPGPR31 1238 +#define IDC_IOPGPR_LO 1239 +#define IDC_IOPGPR_HI 1240 +#define IDC_IOPGPR_PC 1241 +#define IDC_IOPGPR15 1242 +#define IDC_IOPGPR14 1243 +#define IDC_IOPGPR13 1244 +#define IDC_IOPGPR12 1245 +#define IDC_IOPGPR11 1246 +#define IDC_IOPGPR10 1247 +#define IDC_IOPGPR9 1248 +#define IDC_IOPGPR8 1249 +#define IDC_IOPGPR7 1250 +#define IDC_IOPGPR6 1251 +#define IDC_IOPGPR5 1252 +#define IDC_IOPGPR4 1253 +#define IDC_BIOSDIR 1254 +#define IDC_IOPGPR3 1254 +#define IDC_PLUGINSDIR 1255 +#define IDC_EDIT2 1256 +#define IDC_BIAS 1256 +#define IDC_USER_NAME 1257 +#define IDC_CPU_MULTI 1258 +#define IDC_CPU_MULTI2 1259 +#define IDC_CPU_GSMULTI 1259 +#define IDC_PS2SILVER_RECT 1259 +#define IDC_CPU_MULTI3 1260 +#define IDC_CPU_FRAMELIMIT 1260 +#define IDC_CPU_FRAMELIMIT2 1261 +#define IDC_CPU_EEREC 1262 +#define IDC_CPU_VU1REC 1263 +#define IDC_CHECK4 1264 +#define IDC_CPU_VU0REC 1264 +#define IDC_CPU_NEWCOP2 1265 +#define IDC_CPU_FORCEABS 1266 +#define IDC_CPU_VU1REC2 1268 +#define IDC_CPU_SVUREC 1268 +#define IDC_LOG 1500 +#define IDC_CPULOG 1500 +#define IDC_MEMLOG 1501 +#define IDC_HWLOG 1502 +#define IDC_DMALOG 1503 +#define IDC_BIOSLOG 1504 +#define IDC_ELFLOG 1505 +#define IDC_FPULOG 1506 +#define IDC_MMILOG 1507 +#define IDC_VU0LOG 1508 +#define IDC_COP0LOG 1509 +#define IDC_VIFLOG 1510 +#define IDC_SPRLOG 1511 +#define IDC_GIFLOG 1512 +#define IDC_SIFLOG 1513 +#define IDC_IPULOG 1514 +#define IDC_VUMICROLOG 1515 +#define IDC_RPCSERVICES 1516 +#define IDC_IOPLOG 1520 +#define IDC_IOPMEMLOG 1521 +#define IDC_IOPHWLOG 1522 +#define IDC_IOPBIOSLOG 1523 +#define IDC_IOPDMALOG 1524 +#define IDC_IOPPADLOG 1525 +#define IDC_IOPGTELOG 1526 +#define IDC_IOPCDRLOG 1527 +#define IDC_IOPGPULOG 1527 +#define IDC_IOPCNTLOG 1529 +#define IDC_SYMLOG 1530 +#define IDC_STDOUTPUTLOG 1531 +#define ID_FILEOPEN 40001 +#define ID_DEBUG_MEMORY_DUMP 40002 +#define ID_FILE_EXIT 40003 +#define ID_RUN_EXECUTE 40004 +#define ID_RUN_RESET 40005 +#define ID_HELP_ABOUT 40006 +#define ID_CONFIG_CONFIGURE 40007 +#define ID_CONFIG_CPU 40008 +#define ID_CONFIG_GRAPHICS 40009 +#define ID_CONFIG_CONTROLLERS 40010 +#define ID_DEBUG_LOGGING 40011 +#define ID_CONFIG_SOUND 40012 +#define ID_CONFIG_CDVDROM 40013 +#define ID_RUN_CMDLINE 40014 +#define ID_FILE_RUNCD 40015 +#define ID_DEBUG_ENTERDEBUGGER 40016 +#define ID_CONFIG_DEV9 40017 +#define ID_FILE_STATES_LOAD_SLOT1 40018 +#define ID_FILE_STATES_LOAD_SLOT2 40019 +#define ID_FILE_STATES_LOAD_SLOT3 40020 +#define ID_FILE_STATES_LOAD_SLOT4 40021 +#define ID_FILE_STATES_LOAD_SLOT5 40022 +#define ID_FILE_STATES_LOAD_OTHER 40023 +#define ID_FILE_STATES_SAVE_SLOT1 40024 +#define ID_FILE_STATES_SAVE_SLOT2 40025 +#define ID_FILE_STATES_SAVE_SLOT3 40026 +#define ID_FILE_STATES_SAVE_SLOT4 40027 +#define ID_FILE_STATES_SAVE_SLOT5 40028 +#define ID_FILE_STATES_SAVE_OTHER 40029 +#define ID_CONFIG_FW 40030 +#define ID_CONFIG_USB 40031 +#define ID_CONFIG_MEMCARDS 40032 +#define IDC_FORMAT1 40033 +#define IDC_FORMAT2 40034 +#define IDC_LIST1 40035 +#define IDC_LIST2 40036 +#define IDC_RELOAD1 40037 +#define IDC_RELOAD2 40038 +#define IDC_COPYTO2 40039 +#define IDC_COPYTO1 40040 +#define IDC_PASTE 40041 +#define IDC_DELETE1 40042 +#define IDC_DELETE2 40043 +#define ID_PATCHBROWSER 40044 +#define ID_NEWPATCH 40045 +#define IDC_NEWPATCH 40045 +#define IDC_PATCHTEXT 40046 +#define IDC_SAVEPATCH 40047 +#define IDC_REFRESHPATCHLIST 40048 +#define IDC_PATCHCRCLIST 40049 +#define IDC_PATCHNAMELIST 40050 +#define IDC_GAMENAMESEARCH 40051 +#define IDC_SEARCHPATCHTEXT 40052 +#define ID_PROCESSLOW 40053 +#define ID_PROCESSNORMAL 40054 +#define ID_PROCESSHIGH 40055 +#define ID_CONSOLE 40056 +#define ID_PATCHES 40057 +#define ID_CONFIG_ADVANCED 40058 +#define ID_INTERLACEHACK 40059 +#define ID_SAFECNTS 40060 +#define ID_SPU2HACK 40061 +#define ID_VSYNCRATE 40062 +#define ID_HELP_HELP 40063 +#define ID_LANGS 50000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 133 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1263 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/x86-64/iR5900Arit.c b/x86-64/iR5900Arit.c new file mode 100644 index 0000000000..482ce5d2fb --- /dev/null +++ b/x86-64/iR5900Arit.c @@ -0,0 +1,542 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD32RtoR(rdreg, rsreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rsreg); + ADD32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Rt_ != 0) { + ADD32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + ADD64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + ADD64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) { + int rdreg; + int rsreg; + int rtreg; + int t0reg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SUB32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + t0reg = _allocTempX86reg(-1); + + MOV32RtoR(t0reg, rsreg); + SUB32RtoR(t0reg, rdreg); + MOV32RtoR(rdreg, t0reg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + + _freeX86reg(t0reg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rsreg); + SUB32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) + { + SUB32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +#endif +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) { + int rdreg; + int rsreg; + int rtreg; + int t0reg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SUB64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + t0reg = _allocTempX86reg(-1); + + MOV64RtoR(t0reg, rsreg); + SUB64RtoR(t0reg, rdreg); + MOV64RtoR(rdreg, t0reg); + + _freeX86reg(t0reg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + SUB64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + SUB64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + AND64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + AND64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + AND64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); +#else + if (_Rt_ == _Rd_) { // Rd&= Rs + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else if (_Rs_ == _Rd_) { // Rd&= Rt + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + AND64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else { // Rd = Rs & Rt + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +#endif +} + +//////////////////////////////////////////////////// +void recOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + OR64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) { + XOR64RtoR(RAX, RAX); + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[0], RAX ); + } else if ( _Rs_ == 0 ) + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else if ( _Rt_ == 0 ) + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +#endif +} + +//////////////////////////////////////////////////// +void recXOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + XOR64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + XOR64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + XOR64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + XOR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + +#endif +} + +//////////////////////////////////////////////////// +void recNOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rtreg); + NOT64R(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rsreg); + NOT64R(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + OR64RtoR(rdreg, rtreg); + NOT64R(rdreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + NOT64R(RAX); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + +#endif +} + +//////////////////////////////////////////////////// +void recSLT( void ) { + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + MOV64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + SETL8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) { + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + MOV64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + SBB64RtoR(EAX, EAX); + NEG64R (EAX); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); +} + +#endif diff --git a/x86-64/iR5900Arit.h b/x86-64/iR5900Arit.h new file mode 100644 index 0000000000..5fcd64d767 --- /dev/null +++ b/x86-64/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/x86-64/iR5900AritImm.c b/x86-64/iR5900AritImm.c new file mode 100644 index 0000000000..a9d1223354 --- /dev/null +++ b/x86-64/iR5900AritImm.c @@ -0,0 +1,314 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + ADD64ItoR(rtreg, _Imm_); + } else + if (_Rs_ == 0) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, _Imm_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV32ItoR(rtreg, _Imm_); + ADD32RtoR(rtreg, rsreg); + SHL64ItoR(rtreg, 32); + SAR64ItoR(rtreg, 32); + } + } + + _clearNeededX86regs(); + +#else + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Imm_ != 0) { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +#endif +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + ADD64ItoR(rtreg, _Imm_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64ItoR(rtreg, _Imm_); + ADD64RtoR(rtreg, rsreg); + } + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + { + return; + } +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64ItoR(RAX, _Imm_); + SETB8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + { + return; + } +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64ItoR(RAX, _Imm_); + SETL8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recANDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + AND64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64RtoR(rtreg, rsreg); + AND64ItoR(rtreg, _ImmU_); + } + } + + _clearNeededX86regs(); + +#else + + if ( _ImmU_ != 0 ) { + if (_Rs_ == _Rt_) { + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + AND32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_ ); + } else { + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + else + { + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } +#endif +} + +//////////////////////////////////////////////////// +void recORI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + OR64ItoR(rtreg, _ImmU_); + } else + if (_Rs_ == 0) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64RtoR(rtreg, rsreg); + OR64ItoR(rtreg, _ImmU_); + } + } + + _clearNeededX86regs(); + +#else + + if (_Rs_ == _Rt_) { + OR32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], _ImmU_ ); + } else { + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + OR64ItoR( RAX, _ImmU_ ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + } + +#endif +} + +//////////////////////////////////////////////////// +void recXORI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + XOR64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + MOV64RtoR(rtreg, rsreg); + XOR64ItoR(rtreg, _ImmU_); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + XOR64ItoR( RAX, _ImmU_ ); + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + +#endif +} + +#endif diff --git a/x86-64/iR5900AritImm.h b/x86-64/iR5900AritImm.h new file mode 100644 index 0000000000..4bd7a0c6bf --- /dev/null +++ b/x86-64/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/x86-64/iR5900Branch.c b/x86-64/iR5900Branch.c new file mode 100644 index 0000000000..6de85ad0c4 --- /dev/null +++ b/x86-64/iR5900Branch.c @@ -0,0 +1,341 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + + if ( _Rs_ == _Rt_ ) + { + SetBranchImm( _Imm_ * 4 + pc/*, 1*/ ); + } + else + { + u32 branchTo = _Imm_ * 4 + pc; + + // SetFPUstate(); + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 2 ] ); + + SetBranch( ); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + if ( _Rs_ == _Rt_ ) + { + return; + } + + // SetFPUstate(); + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 2 ] ); + + SetBranch( ); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//#if 0 +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLEZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j8Ptr[ 1 ] = JG8( 0 ); + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j8Ptr[ 2 ] = JNZ8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 3 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 1 ] ); + x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 3 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGTZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j8Ptr[ 1 ] = JL8( 0 ); + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j8Ptr[ 2 ] = JZ8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 3 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 1 ] ); + x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 3 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBLTZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 1 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 1 ] ); + + SetBranch( ); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLEZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGTZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 1 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&target, _Imm_ * 4 + pc ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + + MOV32ItoM( (u32)&cpuRegs.pc, pc + 4 ); + iRet( TRUE ); + + x86SetJ8( j8Ptr[ 2 ] ); + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 1 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&cpuRegs.pc, pc + 4 ); + iRet( TRUE ); + + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + + MOV32ItoM( (u32)&target, _Imm_ * 4 + pc ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZL ); + branch = 2; +} +#endif diff --git a/x86-64/iR5900Branch.h b/x86-64/iR5900Branch.h new file mode 100644 index 0000000000..3370b8a4cf --- /dev/null +++ b/x86-64/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/x86-64/iR5900Jump.c b/x86-64/iR5900Jump.c new file mode 100644 index 0000000000..d879ec4aff --- /dev/null +++ b/x86-64/iR5900Jump.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + SetBranchImm(_Target_ * 4 + ( pc & 0xf0000000 )/*, 0*/); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.GPR.r[31].UL[ 0 ], pc + 4 ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[31].UL[ 1 ], 0 ); + + SetBranchImm(_Target_ * 4 + ( pc & 0xf0000000 )/*, 0*/); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_ ); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + if ( _Rd_ ) { + MOV64ItoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], pc + 4 ); + } + + SetBranchReg( _Rs_ ); +} + +#endif diff --git a/x86-64/iR5900Jump.h b/x86-64/iR5900Jump.h new file mode 100644 index 0000000000..d35f87c690 --- /dev/null +++ b/x86-64/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/x86-64/iR5900LoadStore.c b/x86-64/iR5900LoadStore.c new file mode 100644 index 0000000000..3642530f67 --- /dev/null +++ b/x86-64/iR5900LoadStore.c @@ -0,0 +1,554 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "VU0.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +#else +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +u64 retValue; +u64 dummyValue[ 4 ]; + +//////////////////////////////////////////////////// +void recLB( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead8RS ); +} + +//////////////////////////////////////////////////// +void recLBU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + iFlushCall(); + CALLFunc( (u32)memRead8RU ); +} + +//////////////////////////////////////////////////// +void recLH( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + iFlushCall(); + CALLFunc( (u32)memRead16RS ); +} + +//////////////////////////////////////////////////// +void recLHU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead16RU ); +} + +void tests() { + SysPrintf("Err\n"); +} + +//////////////////////////////////////////////////// +void recLW( void ) { + int rsreg; + int rtreg; + int t0reg; + int t1reg; + int t2reg; + +#if 0 +//def ENABLE_REGCACHING + + _freeX86regs(); + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + t0reg = _allocTempX86reg(-1); + t1reg = _allocTempX86reg(-1); + t2reg = _allocTempX86reg(-1); + + MOV32RtoR(t0reg, rsreg); + if (_Imm_ != 0) { + ADD32ItoR(t0reg, _Imm_); + } + MOV32RtoR(t2reg, t0reg); + SHR32ItoR(t0reg, 12); + + MOV64MtoR(t1reg, (u32)&memLUTR); + MOV64RmStoR(t1reg, t1reg, t0reg, 3); + + CMP64ItoR(t1reg, 0x10); + j8Ptr[0] = JL8(0); + + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + AND32ItoR(t2reg, 0xfff); + LogX86(); + MOV64RmStoR(rtreg, t1reg, t2reg, 0); + _clearNeededX86regs(); + _freeX86regs(); + +// j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RS ); + +// x86SetJ8(j8Ptr[1]); + +#else + + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RS ); + +#endif +} + +//////////////////////////////////////////////////// +void recLWU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RU ); +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LWR ); +} + +//////////////////////////////////////////////////// +void recLD( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) + { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead64 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_); + } + AND32ItoR( EDI, ~0xf ); + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead128 ); +} + +//////////////////////////////////////////////////// +void recSB( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite16 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite32 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV64MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite64 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + AND32ItoR( EDI, ~0xf ); + + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite128 ); +} +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + if ( Config.Regcaching ) + { + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.code, cpuRegs.code ); + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.pc, pc ); + + GRec_Instruction( GREC_INST_CALL, LWC1, NULL, 0, GREC_TRUE ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (u32)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memRead32 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + if ( Config.Regcaching ) + { + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.code, cpuRegs.code ); + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.pc, pc ); + + GRec_Instruction( GREC_INST_CALL, SWC1, NULL, 0, GREC_TRUE ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (u32)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memWrite32 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "LQC2 not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (u32)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (u32)&dummyValue ); + } + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memRead128 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + if ( Config.Regcaching ) + { + GRecAssert( GREC_FALSE, "SQC2 not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (u32)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memWrite128 ); + ADD32ItoR( ESP, 8 ); + } +} +*/ +#endif diff --git a/x86-64/iR5900LoadStore.h b/x86-64/iR5900LoadStore.h new file mode 100644 index 0000000000..1a5b99ee7b --- /dev/null +++ b/x86-64/iR5900LoadStore.h @@ -0,0 +1,56 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSQ( void ); +void recSDL( void ); +void recSDR( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +#endif diff --git a/x86-64/iR5900Move.c b/x86-64/iR5900Move.c new file mode 100644 index 0000000000..46302a6f2f --- /dev/null +++ b/x86-64/iR5900Move.c @@ -0,0 +1,256 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#else +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLUI( void ) { + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, (s32)(_Imm_ << 16)); + _clearNeededX86regs(); +#else + MOV64ItoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (s32)(_Imm_ << 16)); +#endif +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching && ConfigNewRec ) + { + GRecLog( "MFHI: PC: 0x%.8X, RD: %d, x86Ptr: 0x%.8x\n", pc, _Rd_, x86Ptr ); + + GRec_Instruction( GREC_INST_MOV64, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.HI.UD[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MFLO not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + } +} +*/ +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MTHI not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MTLO not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +*/ +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching ) + { + GRecLog( "MOVZ: PC: 0x%.8X, RD: %d, RT: %d, RS: %d, x86Ptr: 0x%.8x\n", + pc, _Rd_, _Rt_, _Rs_, x86Ptr ); + + GRec_Instruction( GREC_INST_CMPIMM64, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], (GRec_u64)0 ); + GRec_Instruction( GREC_INST_MOVCC64, GREC_CMP_Z, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + } +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching ) + { + GRecLog( "MOVN: PC: 0x%.8X, RD: %d, RT: %d, RS: %d, x86Ptr: 0x%.8x\n", + pc, _Rd_, _Rt_, _Rs_, x86Ptr ); + + GRec_Instruction( GREC_INST_CMPIMM64, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], (GRec_u64)0 ); + GRec_Instruction( GREC_INST_MOVCC64, GREC_CMP_NZ, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + } +} +*/ +#endif diff --git a/x86-64/iR5900Move.h b/x86-64/iR5900Move.h new file mode 100644 index 0000000000..ae501e334e --- /dev/null +++ b/x86-64/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/x86-64/iR5900MultDiv.c b/x86-64/iR5900MultDiv.c new file mode 100644 index 0000000000..0d84b8efaa --- /dev/null +++ b/x86-64/iR5900MultDiv.c @@ -0,0 +1,138 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC(DIV); +REC_FUNC(DIVU); + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); +} + +#endif diff --git a/x86-64/iR5900MultDiv.h b/x86-64/iR5900MultDiv.h new file mode 100644 index 0000000000..243fd5c18a --- /dev/null +++ b/x86-64/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/x86-64/iR5900Shift.c b/x86-64/iR5900Shift.c new file mode 100644 index 0000000000..3950c07b50 --- /dev/null +++ b/x86-64/iR5900Shift.c @@ -0,0 +1,761 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#else + + +//////////////////////////////////////////////////// +void recDSRA( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SAR64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRA32(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SAR64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SAR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recSLL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_ + 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, _Sa_ + 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHL32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +#endif +} + +//////////////////////////////////////////////////// +void recSRL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR32ItoR(rdreg, _Sa_); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + if (_Sa_) { + SHR32ItoR(rdreg, _Sa_); + } + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHR32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +#endif +} + +//////////////////////////////////////////////////// +void recSRA(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR32ItoR(rdreg, _Sa_); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + if (_Sa_) { + SAR32ItoR(rdreg, _Sa_); + } + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SHL64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHL64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRL( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SHR64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLL32(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHL64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SHR64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + + +//////////////////////////////////////////////////// +void recSLLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recSRLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recSRAV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHL64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRAV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SAR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +#endif + diff --git a/x86-64/iR5900Shift.h b/x86-64/iR5900Shift.h new file mode 100644 index 0000000000..b7b3592691 --- /dev/null +++ b/x86-64/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/x86/iCP0.c b/x86/iCP0.c new file mode 100644 index 0000000000..9c4043e758 --- /dev/null +++ b/x86/iCP0.c @@ -0,0 +1,245 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iCP0.h" + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +#ifndef CP0_RECOMPILE + +REC_SYS(MFC0); +REC_SYS(MTC0); +REC_SYS(BC0F); +REC_SYS(BC0T); +REC_SYS(BC0FL); +REC_SYS(BC0TL); +REC_SYS(TLBR); +REC_SYS(TLBWI); +REC_SYS(TLBWR); +REC_SYS(TLBP); +REC_SYS(ERET); +REC_SYS(DI); +REC_SYS(EI); + +#else + +//////////////////////////////////////////////////// +//REC_SYS(MTC0); +//////////////////////////////////////////////////// +REC_SYS(BC0F); +//////////////////////////////////////////////////// +REC_SYS(BC0T); +//////////////////////////////////////////////////// +REC_SYS(BC0FL); +//////////////////////////////////////////////////// +REC_SYS(BC0TL); +//////////////////////////////////////////////////// +REC_SYS(TLBR); +//////////////////////////////////////////////////// +REC_SYS(TLBWI); +//////////////////////////////////////////////////// +REC_SYS(TLBWR); +//////////////////////////////////////////////////// +REC_SYS(TLBP); +//////////////////////////////////////////////////// +REC_SYS(ERET); +//////////////////////////////////////////////////// +REC_SYS(DI); +//////////////////////////////////////////////////// +REC_SYS(EI); + +//////////////////////////////////////////////////// +extern u32 s_iLastCOP0Cycle; + +void recMFC0( void ) +{ + int mmreg; + + if ( ! _Rt_ ) return; + + if( _Rd_ == 9 ) { + MOV32MtoR( EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ] ); + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + ADD32RtoR(EAX, ECX); + SUB32MtoR(EAX, (u32)&s_iLastCOP0Cycle); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + MOV32RtoM((u32)&cpuRegs.CP0.r[ _Rd_ ], EAX); + + _deleteEEreg(_Rt_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else EEINST_RESETHASLIVE1(_Rt_); + return; + } + + _eeOnWriteReg(_Rt_, 1); + + if( EEINST_ISLIVE1(_Rt_) ) { + _deleteEEreg(_Rt_, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + + if( (mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + SetMMXstate(); + } + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + + if( EEINST_ISLIVE2(_Rt_) ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + } + else { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + } + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + } +} + +void recMTC0() +{ + if( GPR_IS_CONST1(_Rt_) ) { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + PUSH32I(g_cpuConstRegs[_Rt_].UL[0]); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + break; + case 9: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + MOV32ItoM((u32)&cpuRegs.CP0.r[9], g_cpuConstRegs[_Rt_].UL[0]); + break; + default: + MOV32ItoM((u32)&cpuRegs.CP0.r[_Rd_], g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + SUB32ItoR(ESP, 4); + _eeMoveGPRtoRm(ESP, _Rt_); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + break; + case 9: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + _eeMoveGPRtoM((u32)&cpuRegs.CP0.r[9], _Rt_); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + break; + default: + _eeMoveGPRtoM((u32)&cpuRegs.CP0.r[_Rd_], _Rt_); + break; + } + } +} + +/*void rec(COP0) { +} + +void rec(BC0F) { +} + +void rec(BC0T) { +} + +void rec(BC0FL) { +} + +void rec(BC0TL) { +} + +void rec(TLBR) { +} + +void rec(TLBWI) { +} + +void rec(TLBWR) { +} + +void rec(TLBP) { +} + +void rec(ERET) { +} +*/ +/* +//////////////////////////////////////////////////// +void recDI( void ) +{ + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status); + AND32ItoR(EAX, ~0x10000); + PUSH32R(EAX); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + +} + +//////////////////////////////////////////////////// +void recEI( void ) +{ + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status); + OR32ItoR(EAX, 0x10000); + PUSH32R(EAX); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + +} +*/ + +#endif diff --git a/x86/iCP0.h b/x86/iCP0.h new file mode 100644 index 0000000000..52e99b710f --- /dev/null +++ b/x86/iCP0.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ICP0_H__ +#define __ICP0_H__ + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +void recMFC0( void ); +void recMTC0( void ); +void recCOP0( void ); +void recBC0F( void ); +void recBC0T( void ); +void recBC0FL( void ); +void recBC0TL( void ); +void recTLBR( void ); +void recTLBWI( void ); +void recTLBWR( void ); +void recTLBP( void ); +void recERET( void ); +void recDI( void ); +void recEI( void ); + +#endif diff --git a/x86/iCore.cpp b/x86/iCore.cpp new file mode 100644 index 0000000000..f4d2578d1b --- /dev/null +++ b/x86/iCore.cpp @@ -0,0 +1,2368 @@ +#include +#include +#include +#include + +extern "C" { + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "ix86/ix86.h" +#include "iCore.h" +#include "R3000A.h" + +u16 g_x86AllocCounter = 0; +u16 g_xmmAllocCounter = 0; +u16 g_mmxAllocCounter = 0; + +u16 x86FpuState, iCWstate; +EEINST* g_pCurInstInfo = NULL; + +u32 g_cpuRegHasLive1 = 0, g_cpuPrevRegHasLive1 = 0; // set if upper 32 bits are live +u32 g_cpuRegHasSignExt = 0, g_cpuPrevRegHasSignExt = 0; // set if upper 32 bits are the sign extension of the lower integer + +// used to make sure regs don't get changed while in recompiler +// use FreezeMMXRegs, FreezeXMMRegs +u8 g_globalMMXSaved = 0, g_globalXMMSaved = 0; +u32 g_recWriteback = 0; + +#ifdef _DEBUG +char g_globalMMXLocked = 0, g_globalXMMLocked = 0; +#endif + +_xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +__declspec(align(16)) u64 g_globalMMXData[8]; +__declspec(align(16)) u64 g_globalXMMData[2*XMMREGS]; + +// X86 caching +_x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; +static int s_x86checknext = 0; + +} // end extern "C" + +#include + +void _initX86regs() { + memset(x86regs, 0, sizeof(x86regs)); + g_x86AllocCounter = 0; + s_x86checknext = 0; +} + +__forceinline u32 _x86GetAddr(int type, int reg) +{ + switch(type&~X86TYPE_VU1) { + case X86TYPE_GPR: return (u32)&cpuRegs.GPR.r[reg]; + case X86TYPE_VI: { + //assert( reg < 16 || reg == REG_R ); + return (type&X86TYPE_VU1)?(u32)&VU1.VI[reg]:(u32)&VU0.VI[reg]; + } + case X86TYPE_MEMOFFSET: return 0; + case X86TYPE_VIMEMOFFSET: return 0; + case X86TYPE_VUQREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUPREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUQWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.q:(u32)&VU0.q; + case X86TYPE_VUPWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.p:(u32)&VU0.p; + case X86TYPE_PSX: return (u32)&psxRegs.GPR.r[reg]; + case X86TYPE_PCWRITEBACK: + return (u32)&g_recWriteback; + case X86TYPE_VUJUMP: + return (u32)&g_recWriteback; + default: assert(0); + } + + return 0; +} + +int _getFreeX86reg(int mode) +{ + int i, tempi; + u32 bestcount = 0x10000; + + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + + for (i=0; i= maxreg ) continue; + if( (mode&MODE_NOFRAME) && reg==EBP ) continue; + + if (x86regs[reg].inuse == 0) { + s_x86checknext = (reg+1)%X86REGS; + return reg; + } + } + + tempi = -1; + for (i=1; i= 0 && reg < 32 ); + +// if( X86_ISVI(type) ) +// assert( reg < 16 || reg == REG_R ); + + // don't alloc EAX and ESP,EBP if MODE_NOFRAME + int oldmode = mode; + int noframe = mode&MODE_NOFRAME; + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + mode &= ~(MODE_NOFRAME|MODE_8BITREG); + int readfromreg = -1; + + if( type != X86TYPE_TEMP ) { + + if( maxreg < X86REGS ) { + // make sure reg isn't in the higher regs + + for(i = maxreg; i < X86REGS; ++i) { + if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg) continue; + + if( mode & MODE_READ ) { + readfromreg = i; + x86regs[i].inuse = 0; + break; + } + else if( mode & MODE_WRITE ) { + x86regs[i].inuse = 0; + break; + } + } + } + + for (i=1; i= maxreg) ) { + if( x86regs[i].mode & MODE_READ ) + readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + + if( x86reg >= 0 ) { + // requested specific reg, so return that instead + if( i != x86reg ) { + if( x86regs[i].mode & MODE_READ ) readfromreg = i; + //if( x86regs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + } + + if( type != X86TYPE_TEMP && !(x86regs[i].mode & MODE_READ) && (mode&MODE_READ)) { + + if( type == X86TYPE_GPR ) _flushConstReg(reg); + + if( X86_ISVI(type) && reg < 16 ) MOVZX32M16toR(i, _x86GetAddr(type, reg)); + else MOV32MtoR(i, _x86GetAddr(type, reg)); + + x86regs[i].mode |= MODE_READ; + } + + x86regs[i].needed = 1; + x86regs[i].mode|= mode; + return i; + } + } + + if (x86reg == -1) { + x86reg = _getFreeX86reg(oldmode); + } + else { + _freeX86reg(x86reg); + } + + x86regs[x86reg].type = type; + x86regs[x86reg].reg = reg; + x86regs[x86reg].mode = mode; + x86regs[x86reg].needed = 1; + x86regs[x86reg].inuse = 1; + + if( mode & MODE_READ ) { + if( readfromreg >= 0 ) MOV32RtoR(x86reg, readfromreg); + else { + if( type == X86TYPE_GPR ) { + + if( reg == 0 ) { + XOR32RtoR(x86reg, x86reg); + } + else { + _flushConstReg(reg); + _deleteMMXreg(MMX_GPR+reg, 1); + _deleteGPRtoXMMreg(reg, 1); + + _eeMoveGPRtoR(x86reg, reg); + + _deleteMMXreg(MMX_GPR+reg, 0); + _deleteGPRtoXMMreg(reg, 0); + } + } + else { + if( X86_ISVI(type) && reg < 16 ) { + if( reg == 0 ) XOR32RtoR(x86reg, x86reg); + else MOVZX32M16toR(x86reg, _x86GetAddr(type, reg)); + } + else MOV32MtoR(x86reg, _x86GetAddr(type, reg)); + } + } +} + + return x86reg; +} + +int _checkX86reg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 && x86reg < X86REGS ); + + if( x86regs[x86reg].inuse && (x86regs[x86reg].mode&MODE_WRITE) ) { + x86regs[x86reg].mode &= ~MODE_WRITE; + + if( X86_ISVI(x86regs[x86reg].type) && x86regs[x86reg].reg < 16 ) { + MOV16RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + else + MOV32RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + + x86regs[x86reg].inuse = 0; +} + +void _freeX86regs() { + int i; + + for (i=0; i= 0 ) return -1; + + if( poffset ) *poffset = x86regs[i].extra; + return i; +} + +// MMX Caching +_mmxregs mmxregs[8], s_saveMMXregs[8]; +static int s_mmxchecknext = 0; + +void _initMMXregs() +{ + memset(mmxregs, 0, sizeof(mmxregs)); + g_mmxAllocCounter = 0; + s_mmxchecknext = 0; +} + +__forceinline void* _MMXGetAddr(int reg) +{ + assert( reg != MMX_TEMP ); + + if( reg == MMX_LO ) return &cpuRegs.LO; + if( reg == MMX_HI ) return &cpuRegs.HI; + if( reg == MMX_FPUACC ) return &fpuRegs.ACC; + + if( reg >= MMX_GPR && reg < MMX_GPR+32 ) return &cpuRegs.GPR.r[reg&31]; + if( reg >= MMX_FPU && reg < MMX_FPU+32 ) return &fpuRegs.fpr[reg&31]; + if( reg >= MMX_COP0 && reg < MMX_COP0+32 ) return &cpuRegs.CP0.r[reg&31]; + + assert( 0 ); + return NULL; +} + +int _getFreeMMXreg() +{ + int i, tempi; + u32 bestcount = 0x10000; + + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) { + _freeMMXreg(i); + return i; + } + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + _freeMMXreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg] & EEINST_MMX) ) { + _freeMMXreg(i); + return i; + } + } + } + + tempi = -1; + for (i=0; i= 0 ) { + if (cpucaps.hasStreamingSIMD2Extensions) { + SSE_MOVHPS_XMM_to_M64((u32)_MMXGetAddr(reg)+8, xmmreg); + if( mode & MODE_READ ) + SSE2_MOVDQ2Q_XMM_to_MM(mmxreg, xmmreg); + + if( xmmregs[xmmreg].mode & MODE_WRITE ) + mmxregs[mmxreg].mode |= MODE_WRITE; + + // don't flush + xmmregs[xmmreg].inuse = 0; + } + else { + _freeXMMreg(xmmreg); + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + + } + } + else { + if( MMX_ISGPR(reg) ) { + if(mode&(MODE_READHALF|MODE_READ)) _flushConstReg(reg-MMX_GPR); + } + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + } + } + + return mmxreg; +} + +int _checkMMXreg(int reg, int mode) +{ + int i; + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !EEINST_ISLIVEMMX(mmxregs[i].reg-MMX_GPR) ) { + return 1; + } + } + } + + // check for dead regs + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + return 1; + } + } + } + + return 0; +} + +void _freeMMXreg(int mmxreg) +{ + assert( mmxreg < MMXREGS ); + if (!mmxregs[mmxreg].inuse) return; + + if (mmxregs[mmxreg].mode & MODE_WRITE ) { + + if( mmxregs[mmxreg].reg >= MMX_GPR && mmxregs[mmxreg].reg < MMX_GPR+32 ) + assert( !(g_cpuHasConstReg & (1<<(mmxregs[mmxreg].reg-MMX_GPR))) ); + + assert( mmxregs[mmxreg].reg != MMX_GPR ); + + if( MMX_IS32BITS(mmxregs[mmxreg].reg) ) + MOVDMMXtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + else + MOVQRtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + + SetMMXstate(); + } + + mmxregs[mmxreg].mode &= ~MODE_WRITE; + mmxregs[mmxreg].inuse = 0; +} + +void _moveMMXreg(int mmxreg) +{ + int i; + if( !mmxregs[mmxreg].inuse ) return; + + for (i=0; iVF[x].UL[0] +#define VU_ACCx_ADDR (u32)&VU->ACC.UL[0] + +static int s_xmmchecknext = 0; + +void _initXMMregs() { + memset(xmmregs, 0, sizeof(xmmregs)); + g_xmmAllocCounter = 0; + s_xmmchecknext = 0; +} + +__forceinline void* _XMMGetAddr(int type, int reg, VURegs *VU) +{ + if (type == XMMTYPE_VFREG ) return (void*)VU_VFx_ADDR(reg); + else if (type == XMMTYPE_ACC ) return (void*)VU_ACCx_ADDR; + else if (type == XMMTYPE_GPRREG) { + if( reg < 32 ) + assert( !(g_cpuHasConstReg & (1<regs[xmmregs[i].reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + _freeXMMreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; iregs[xmmregs[i].reg] & EEINST_XMM) ) { + _freeXMMreg(i); + return i; + } + } + } + + tempi = -1; + bestcount = 0xffff; + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + xmmregs[i].needed = 1; + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ) ) { + SSE_MOVAPS_M128_to_XMM(i, VU_VFx_ADDR(vfreg)); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_VFREG; + xmmregs[xmmreg].reg = vfreg; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_VFx_ADDR(xmmregs[xmmreg].reg)); + } + + return xmmreg; +} + +int _checkXMMreg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ)) { + SSE_MOVAPS_M128_to_XMM(i, VU_ACCx_ADDR); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].needed = 1; + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_ACC; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + xmmregs[xmmreg].reg = 0; + + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_ACCx_ADDR); + } + + return xmmreg; +} + +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode) { + int i; + + for (i=0; i= 0 ) { + // transfer + if (cpucaps.hasStreamingSIMD2Extensions ) { + + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(xmmreg, mmxreg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(xmmreg, xmmreg); + SSE2_PUNPCKHQDQ_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + + if( mmxregs[mmxreg].mode & MODE_WRITE ) { + + // instead of setting to write, just flush to mem + if( !(mode & MODE_WRITE) ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], mmxreg); + } + //xmmregs[xmmreg].mode |= MODE_WRITE; + } + + // don't flush + mmxregs[mmxreg].inuse = 0; + } + else { + _freeMMXreg(mmxreg); + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + else { + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + } + else { + _deleteMMXreg(MMX_GPR+gprreg, 0); + } + + return xmmreg; +} + +int _allocFPACCtoXMMreg(int xmmreg, int mode) { + int i; + + for (i=0; iregs[xmmregs[i].reg]&EEINST_USED) ) { + return 1; + } + } + } + return 0; +} + +void _moveXMMreg(int xmmreg) +{ + int i; + if( !xmmregs[xmmreg].inuse ) return; + + for (i=0; i= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) { + SSE2_MOVD_XMM_to_R(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE) ) { + MOVD32MMXtoR(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(to, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + } + } +} + +void _eeMoveGPRtoM(u32 to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_M32(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVDMMXtoM(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoM(to, EAX ); + } + } +} + +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_Rm(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVD32MMXtoRm(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoRm(to, EAX ); + } + } +} + +// PSX +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoR( to, g_psxConstRegs[fromgpr] ); + else { + // check x86 + MOV32MtoR(to, (int)&psxRegs.GPR.r[ fromgpr ] ); + } +} + +void _psxMoveGPRtoM(u32 to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_psxConstRegs[fromgpr] ); + else { + // check x86 + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ fromgpr ] ); + MOV32RtoM(to, EAX ); + } +} + +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 ); + else { + // check x86 + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ fromgpr ] ); + MOV32RtoRm(to, EAX ); + } +} + +void _recPushReg(int mmreg) +{ + if( IS_XMMREG(mmreg) ) { + SUB32ItoR(ESP, 4); + SSEX_MOVD_XMM_to_Rm(ESP, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + SUB32ItoR(ESP, 4); + MOVD32MMXtoRm(ESP, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + PUSH32I(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + PUSH32I(g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else PUSH32R(mmreg); +} + +void _signExtendSFtoM(u32 mem) +{ + LAHF(); + SAR16ItoR(EAX, 15); + CWDE(); + MOV32RtoM(mem, EAX ); +} + +int _signExtendMtoMMX(x86MMXRegType to, u32 mem) +{ + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, mem); + MOVQRtoR(to, t0reg); + PSRADItoR(t0reg, 31); + PUNPCKLDQRtoR(to, t0reg); + _freeMMXreg(t0reg); + return to; +} + +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg) +{ + assert( to >= 0 && from >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + EEINST_RESETHASLIVE1(gprreg); + if( to != from ) MOVQRtoR(to, from); + return to; + } + + if( to == from ) return _signExtendGPRtoMMX(to, gprreg, 0); + if( !(g_pCurInstInfo->regs[gprfromreg]&EEINST_LASTUSE) ) { + if( EEINST_ISLIVEMMX(gprfromreg) ) { + MOVQRtoR(to, from); + return _signExtendGPRtoMMX(to, gprreg, 0); + } + } + + // from is free for use + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + + if( EEINST_ISLIVEMMX(gprfromreg) ) { + _freeMMXreg(from); + } + + MOVQRtoR(to, from); + PSRADItoR(from, 31); + PUNPCKLDQRtoR(to, from); + return to; + } + else { + MOVQRtoR(to, from); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], from); + PSRADItoR(from, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], from); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift) +{ + assert( to >= 0 && shift >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + if( shift > 0 ) PSRADItoR(to, shift); + EEINST_RESETHASLIVE1(gprreg); + return to; + } + + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, to); + PSRADItoR(to, 31); + if( shift > 0 ) PSRADItoR(t0reg, shift); + PUNPCKLDQRtoR(t0reg, to); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[to]; + mmxregs[to].inuse = 0; + return t0reg; + } + else { + // will be used in the future as mmx + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + + // read again + MOVQMtoR(to, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + mmxregs[to].mode &= ~MODE_WRITE; + return to; + } + } + else { + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +__declspec(align(16)) u32 s_zeros[4] = {0}; +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy) +{ + int t0reg; +// if( g_xmmtypes[from] == XMMT_FPS && (!candestroy || _hasFreeXMMreg()) ) { +// // special floating point implementation +// // NOTE: doesn't sign extend 0x80000000 +// xmmregs[from].needed = 1; +// t0reg = _allocTempXMMreg(XMMT_FPS, -1); +// SSE_XORPS_XMM_to_XMM(t0reg, t0reg); +// SSE_MOVSS_XMM_to_M32(to, from); +// SSE_CMPNLESS_XMM_to_XMM(t0reg, from); +// SSE_MOVSS_XMM_to_M32(to+4, t0reg); +// _freeXMMreg(t0reg); +// return 0; +// } +// else { + g_xmmtypes[from] = XMMT_INT; + if( candestroy ) { + if( g_xmmtypes[from] == XMMT_FPS || !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVSS_XMM_to_M32(to, from); + else SSE2_MOVD_XMM_to_M32(to, from); + +// if( g_xmmtypes[from] == XMMT_FPS ) { +// SSE_CMPLTSS_M32_to_XMM(from, (u32)&s_zeros[0]); +// SSE_MOVSS_XMM_to_M32(to+4, from); +// return 1; +// } +// else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRAD_I8_to_XMM(from, 31); + SSE2_MOVD_XMM_to_M32(to+4, from); + return 1; + } + else { + SSE_MOVSS_XMM_to_M32(to+4, from); + SAR32ItoM(to+4, 31); + return 0; + } +// } + } + else { + // can't destroy and type is int + assert( g_xmmtypes[from] == XMMT_INT ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _hasFreeXMMreg() ) { + xmmregs[from].needed = 1; + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, from); + SSE2_PSRAD_I8_to_XMM(from, 31); + SSE2_MOVD_XMM_to_M32(to, t0reg); + SSE2_MOVD_XMM_to_M32(to+4, from); + + // swap xmm regs.. don't ask + xmmregs[t0reg] = xmmregs[from]; + xmmregs[from].inuse = 0; + } + else { + SSE2_MOVD_XMM_to_M32(to+4, from); + SSE2_MOVD_XMM_to_M32(to, from); + SAR32ItoM(to+4, 31); + } + } + else { + SSE_MOVSS_XMM_to_M32(to+4, from); + SSE_MOVSS_XMM_to_M32(to, from); + SAR32ItoM(to+4, 31); + } + + return 0; + } + //} + + assert(0); +} + +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode) +{ + if( pinst->regs[gprreg] & EEINST_XMM ) return _allocGPRtoXMMreg(-1, gprreg, mode); + + return _checkXMMreg(XMMTYPE_GPRREG, gprreg, mode); +} + +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode) +{ + if( pinst->fpuregs[fpureg] & EEINST_XMM ) return _allocFPtoXMMreg(-1, fpureg, mode); + + return _checkXMMreg(XMMTYPE_FPREG, fpureg, mode); +} + +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode) +{ + if( pinst->regs[reg] & EEINST_MMX ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + + return _checkMMXreg(MMX_GPR+reg, mode); +} + +void _recClearInst(EEINST* pinst) +{ + memset(&pinst->regs[0], EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2, sizeof(pinst->regs)); + memset(&pinst->fpuregs[0], EEINST_LIVE0, sizeof(pinst->fpuregs)); + memset(&pinst->info, 0, sizeof(EEINST)-sizeof(pinst->regs)-sizeof(pinst->fpuregs)); +} + +// returns nonzero value if reg has been written between [startpc, endpc-4] +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == xmmtype && pinst->readReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +void _recFillRegister(EEINST* pinst, int type, int reg, int write) +{ + int i = 0; + if( write ) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == XMMTYPE_TEMP ) { + pinst->writeType[i] = type; + pinst->writeReg[i] = reg; + return; + } + } + assert(0); + } + else { + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == XMMTYPE_TEMP ) { + pinst->readType[i] = type; + pinst->readReg[i] = reg; + return; + } + } + assert(0); + } +} + +// Writebacks // +void _recClearWritebacks() +{ +} + +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent) +{ +} + +EEINSTWRITEBACK* _recCheckWriteBack(int cycle) +{ + return NULL; +} + +__declspec(align(16)) static u32 s_ones[2] = {0xffffffff, 0xffffffff}; + +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op) +{ + switch(op) { + case 0: PANDRtoR(to, from); break; + case 1: PORRtoR(to, from); break; + case 2: PXORRtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op) +{ + switch(op) { + case 0: PANDMtoR(to, from); break; + case 1: PORMtoR(to, from); break; + case 2: PXORMtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND32RtoM(to, from); break; + case 1: OR32RtoM(to, from); break; + case 2: XOR32RtoM(to, from); break; + case 3: OR32RtoM(to, from); break; + } +} + +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32MtoR(to, from); break; + case 1: OR32MtoR(to, from); break; + case 2: XOR32MtoR(to, from); break; + case 3: OR32MtoR(to, from); break; + } +} + +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoR(to, from); break; + case 1: OR32ItoR(to, from); break; + case 2: XOR32ItoR(to, from); break; + case 3: OR32ItoR(to, from); break; + } +} + +void LogicalOp32ItoM(u32 to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoM(to, from); break; + case 1: OR32ItoM(to, from); break; + case 2: XOR32ItoM(to, from); break; + case 3: OR32ItoM(to, from); break; + } +} + +using namespace std; + +struct BASEBLOCKS +{ + // 0 - ee, 1 - iop + inline void Add(BASEBLOCKEX*); + inline void Remove(BASEBLOCKEX*); + inline int Get(u32 startpc); + inline void Reset(); + + inline BASEBLOCKEX** GetAll(int* pnum); + + vector blocks; +}; + +void BASEBLOCKS::Add(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + + switch(blocks.size()) { + case 0: + blocks.push_back(pex); + return; + case 1: + assert( blocks.front()->startpc != pex->startpc ); + + if( blocks.front()->startpc < pex->startpc ) { + blocks.push_back(pex); + } + else blocks.insert(blocks.begin(), pex); + + return; + + default: + { + int imin = 0, imax = blocks.size(), imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > pex->startpc ) imax = imid; + else imin = imid+1; + } + + assert( imin == blocks.size() || blocks[imin]->startpc > pex->startpc ); + if( imin > 0 ) assert( blocks[imin-1]->startpc < pex->startpc ); + blocks.insert(blocks.begin()+imin, pex); + + return; + } + } +} + +int BASEBLOCKS::Get(u32 startpc) +{ + switch(blocks.size()) { + case 1: + return 0; + case 2: + return blocks.front()->startpc < startpc; + + default: + { + int imin = 0, imax = blocks.size()-1, imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > startpc ) imax = imid; + else if( blocks[imid]->startpc == startpc ) return imid; + else imin = imid+1; + } + + assert( blocks[imin]->startpc == startpc ); + return imin; + } + } +} + +void BASEBLOCKS::Remove(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + int i = Get(pex->startpc); + assert( blocks[i] == pex ); + blocks.erase(blocks.begin()+i); +} + +void BASEBLOCKS::Reset() +{ + blocks.resize(0); + blocks.reserve(512); +} + +BASEBLOCKEX** BASEBLOCKS::GetAll(int* pnum) +{ + assert( pnum != NULL ); + *pnum = blocks.size(); + return &blocks[0]; +} + +static BASEBLOCKS s_vecBaseBlocksEx[2]; + +void AddBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Add(pex); +} + +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu) +{ + return s_vecBaseBlocksEx[cpu].blocks[s_vecBaseBlocksEx[cpu].Get(startpc)]; +} + +void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Remove(pex); +} + +void ResetBaseBlockEx(int cpu) +{ + s_vecBaseBlocksEx[cpu].Reset(); +} + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu) +{ + return s_vecBaseBlocksEx[cpu].GetAll(pnum); +} diff --git a/x86/iCore.h b/x86/iCore.h new file mode 100644 index 0000000000..7fdc856698 --- /dev/null +++ b/x86/iCore.h @@ -0,0 +1,416 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_CORE_RECOMPILER_ +#define _PCSX2_CORE_RECOMPILER_ + +#include "ivumicro.h" + +// used to keep block information +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +typedef struct _BASEBLOCK +{ + u32 pFnptr : 28; + u32 uType : 4; + u32 startpc; +} BASEBLOCK; + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +// extra block info (only valid for start of fn) +typedef struct _BASEBLOCKEX +{ + u16 size; // size in dwords + u16 dummy; + u32 startpc; // for debugging? + +#ifdef PCSX2_DEVBUILD + u32 visited; // number of times called + LARGE_INTEGER ltime; // regs it assumes to have set already +#endif + +} BASEBLOCKEX; + +#define GET_BLOCKTYPE(b) ((b)->Type) +#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + +#define FPU_STATE 0 +#define MMX_STATE 1 + +#define X86TYPE_TEMP 0 +#define X86TYPE_GPR 1 +#define X86TYPE_VI 2 +#define X86TYPE_MEMOFFSET 3 +#define X86TYPE_VIMEMOFFSET 4 +#define X86TYPE_VUQREAD 5 +#define X86TYPE_VUPREAD 6 +#define X86TYPE_VUQWRITE 7 +#define X86TYPE_VUPWRITE 8 +#define X86TYPE_PSX 9 +#define X86TYPE_PCWRITEBACK 10 +#define X86TYPE_VUJUMP 12 // jump from random mem (g_recWriteback) + +#define X86TYPE_VU1 0x80 + +#define X86_ISVI(type) ((type&~X86TYPE_VU1) == X86TYPE_VI) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u8 type; // X86TYPE_ + u16 counter; + u32 extra; // extra info assoc with the reg +} _x86regs; + +extern _x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; + +void _initX86regs(); +int _getFreeX86reg(int mode); +int _allocX86reg(int x86reg, int type, int reg, int mode); +void _deleteX86reg(int type, int reg, int flush); +int _checkX86reg(int type, int reg, int mode); +void _addNeededX86reg(int type, int reg); +void _clearNeededX86regs(); +void _freeX86reg(int x86reg); +void _freeX86regs(); + +void _eeSetLoadStoreReg(int gprreg, u32 offset, int x86reg); +int _eeGeLoadStoreReg(int gprreg, int* poffset); + +void recReset(); + +// when using mmx/xmm regs, use; 0 is load +// freezes no matter the state +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +void SetFPUstate(); +void SetMMXstate(); + +#define MODE_READ 1 +#define MODE_WRITE 2 +#define MODE_READHALF 4 // read only low 64 bits +#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF +#define MODE_VUZ 0x10 // z only doesn't work for now +#define MODE_VUXYZ (MODE_VUZ|MODE_VUXY) // vector only has xyz valid (real w is in memory) +#define MODE_NOFLUSH 0x20 // can't flush reg to mem +#define MODE_NOFRAME 0x40 // when allocating x86regs, don't use ebp reg +#define MODE_8BITREG 0x80 // when allocating x86regs, use only eax, ecx, edx, and ebx + +// max is 0x7f, when 0x80 is set, need to flush reg +#define MMX_GET_CACHE(ptr, index) ((u8*)ptr)[index] +#define MMX_SET_CACHE(ptr, ind3, ind2, ind1, ind0) ((u32*)ptr)[0] = (ind3<<24)|(ind2<<16)|(ind1<<8)|ind0; +#define MMX_GPR 0 +#define MMX_HI 32 +#define MMX_LO 33 +#define MMX_FPUACC 34 +#define MMX_FPU 64 +#define MMX_COP0 96 +#define MMX_TEMP 0x7f + +#define MMX_IS32BITS(x) (((x)>=MMX_FPU&&(x)= MMX_GPR && (x) < MMX_GPR+34) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u16 counter; +} _mmxregs; + +void _initMMXregs(); +int _getFreeMMXreg(); +int _allocMMXreg(int MMXreg, int reg, int mode); +void _addNeededMMXreg(int reg); +int _checkMMXreg(int reg, int mode); +void _clearNeededMMXregs(); +void _deleteMMXreg(int reg, int flush); +void _freeMMXreg(int mmxreg); +void _moveMMXreg(int mmxreg); // instead of freeing, moves it to a diff location +void _flushMMXregs(); +u8 _hasFreeMMXreg(); +void _freeMMXregs(); +int _getNumMMXwrite(); + +void _flushCachedRegs(); +void _flushConstRegs(); +void _flushConstReg(int reg); + +// return type: 0 - const, 1 - mmx, 2 - xmm +#define PROCESS_EE_MMX 0x01 +#define PROCESS_EE_XMM 0x02 + +// currently only used in FPU +#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem +#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem + +// not used in VU recs +#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs +#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs +#define PROCESS_EE_LO 0x40 // lo reg is valid +#define PROCESS_EE_HI 0x80 // hi reg is valid +#define PROCESS_EE_ACC 0x40 // acc reg is valid + +// used in VU recs +#define PROCESS_VU_UPDATEFLAGS 0x10 +#define PROCESS_VU_SUPER 0x40 // set if using supervu recompilation +#define PROCESS_VU_COP2 0x80 // simple cop2 + +#define EEREC_S (((info)>>8)&0xf) +#define EEREC_T (((info)>>12)&0xf) +#define EEREC_D (((info)>>16)&0xf) +#define EEREC_LO (((info)>>20)&0xf) +#define EEREC_HI (((info)>>24)&0xf) +#define EEREC_ACC (((info)>>20)&0xf) +#define EEREC_TEMP (((info)>>24)&0xf) + +#define PROCESS_EE_SET_S(reg) ((reg)<<8) +#define PROCESS_EE_SET_T(reg) ((reg)<<12) +#define PROCESS_EE_SET_D(reg) ((reg)<<16) +#define PROCESS_EE_SET_LO(reg) ((reg)<<20) +#define PROCESS_EE_SET_HI(reg) ((reg)<<24) +#define PROCESS_EE_SET_ACC(reg) ((reg)<<20) + +#define PROCESS_VU_SET_ACC(reg) PROCESS_EE_SET_ACC(reg) +#define PROCESS_VU_SET_TEMP(reg) ((reg)<<24) + +// special info not related to above flags +#define PROCESS_CONSTS 1 +#define PROCESS_CONSTT 2 + +#define XMM_CONV_VU(VU) (VU==&VU1) + +#define XMMTYPE_TEMP 0 // has to be 0 +#define XMMTYPE_VFREG 1 +#define XMMTYPE_ACC 2 +#define XMMTYPE_FPREG 3 +#define XMMTYPE_FPACC 4 +#define XMMTYPE_GPRREG 5 + +// lo and hi regs +#define XMMGPR_LO MMX_LO +#define XMMGPR_HI MMX_HI +#define XMMFPU_ACC 32 + +typedef struct { + u8 inuse; + u8 reg; + u8 type; + u8 mode; + u8 needed; + u8 VU; // 0 = VU0, 1 = VU1 + u16 counter; +} _xmmregs; + +void _initXMMregs(); +int _getFreeXMMreg(); +int _allocTempXMMreg(XMMSSEType type, int xmmreg); +int _allocVFtoXMMreg(VURegs *VU, int xmmreg, int vfreg, int mode); +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode); +int _allocGPRtoXMMreg(int xmmreg, int gprreg, int mode); +int _allocACCtoXMMreg(VURegs *VU, int xmmreg, int mode); +int _allocFPACCtoXMMreg(int xmmreg, int mode); +int _checkXMMreg(int type, int reg, int mode); +void _addNeededVFtoXMMreg(int vfreg); +void _addNeededACCtoXMMreg(); +void _addNeededFPtoXMMreg(int fpreg); +void _addNeededFPACCtoXMMreg(); +void _addNeededGPRtoXMMreg(int gprreg); +void _clearNeededXMMregs(); +void _deleteVFtoXMMreg(int reg, int vu, int flush); +void _deleteACCtoXMMreg(int vu, int flush); +void _deleteGPRtoXMMreg(int reg, int flush); +void _deleteFPtoXMMreg(int reg, int flush); +void _freeXMMreg(int xmmreg); +void _moveXMMreg(int xmmreg); // instead of freeing, moves it to a diff location +void _flushXMMregs(); +u8 _hasFreeXMMreg(); +void _freeXMMregs(); +int _getNumXMMwrite(); + +// Constants used for controlling iFlushCall, _psxFlushCall +#define FLUSH_CACHED_REGS 1 +#define FLUSH_FLUSH_XMM 2 +#define FLUSH_FREE_XMM 4 // both flushes and frees +#define FLUSH_FLUSH_MMX 8 +#define FLUSH_FREE_MMX 16 // both flushes and frees + +#define FLUSH_EVERYTHING 0xff +// no freeing, used when callee won't destroy mmx/xmm regs +#define FLUSH_NODESTROY (FLUSH_CACHED_REGS|FLUSH_FLUSH_XMM|FLUSH_FLUSH_MMX) +// used when regs aren't going to be changed be callee +#define FLUSH_NOCONST (FLUSH_FREE_XMM|FLUSH_FREE_MMX) + +// Note: All functions with _ee prefix are for EE only + +// finds where the GPR is stored and moves lower 32 bits to EAX +void _eeMoveGPRtoR(x86IntRegType to, int fromgpr); +void _eeMoveGPRtoM(u32 to, int fromgpr); +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr); + +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr); +void _psxMoveGPRtoM(u32 to, int fromgpr); +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr); + +// uses MEM_MMXTAG/MEM_XMMTAG to differentiate between the regs +void _recPushReg(int mmreg); + +void _signExtendSFtoM(u32 mem); +int _signExtendMtoMMX(x86MMXRegType to, u32 mem); +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg); + +// returns new index of reg, lower 32 bits already in mmx +// shift is used when the data is in the top bits of the mmx reg to begin with +// a negative shift is for sign extension +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift); +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns true if reg destroyed + +// Defines for passing register info + +// only valid during writes. If write128, then upper 64bits are in an mmxreg +// (mmreg&0xf). Constant is used from gprreg ((mmreg>>16)&0x1f) +#define MEM_EECONSTTAG 0x0100 +#define MEM_PSXCONSTTAG 0x0200 +// mmreg is mmxreg +#define MEM_MMXTAG 0x0800 +// mmreg is xmmreg +#define MEM_XMMTAG 0x8000 + +#define IS_CONSTREG(reg) ((reg)&MEM_EECONSTTAG) +#define IS_PSXCONSTREG(reg) ((reg)&MEM_PSXCONSTTAG) +#define IS_MMXREG(reg) ((reg)&MEM_MMXTAG) +#define IS_XMMREG(reg) ((reg)&MEM_XMMTAG) + +////////////////////// +// Instruction Info // +////////////////////// +#define EEINST_LIVE0 1 // if var is ever used (read or write) +#define EEINST_LIVE1 2 // if cur var's next 32 bits are needed +#define EEINST_LIVE2 4 // if cur var's next 64 bits are needed +#define EEINST_LASTUSE 8 // if var isn't written/read anymore +#define EEINST_MMX 0x10 // var will be used in mmx ops +#define EEINST_XMM 0x20 // var will be used in xmm ops (takes precedence +#define EEINST_USED 0x40 + +#define EEINSTINFO_COP1 1 +#define EEINSTINFO_COP2 2 +#define EEINSTINFO_NOREC 4 // if set, inst is recompiled alone +#define EEINSTINFO_COREC 8 // if set, inst is recompiled with another similar inst +#define EEINSTINFO_MMX EEINST_MMX +#define EEINSTINFO_XMM EEINST_XMM + +typedef struct _EEINST +{ + u8 regs[34]; // includes HI/LO (HI=32, LO=33) + u8 fpuregs[33]; // ACC=32 + u8 info; // extra info, if 1 inst is COP1, 2 inst is COP2. Also uses EEINST_MMX|EEINST_XMM + + // uses XMMTYPE_ flags; if type == XMMTYPE_TEMP, not used + u8 writeType[3], writeReg[3]; // reg written in this inst, 0 if no reg + u8 readType[4], readReg[4]; + + // valid if info & EEINSTINFO_COP2 + int cycle; // cycle of inst (at offset from block) + _VURegsNum vuregs; + + u8 numpeeps; // number of peephole optimizations +} EEINST; + +extern EEINST* g_pCurInstInfo; // info for the cur instruction +void _recClearInst(EEINST* pinst); + +// returns the number of insts + 1 until written (0 if not written) +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg); +// returns the number of insts + 1 until used (0 if not used) +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg); +void _recFillRegister(EEINST* pinst, int type, int reg, int write); + +#define EEINST_ISLIVEMMX(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1)) +#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) +#define EEINST_ISLIVE1(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE1) +#define EEINST_ISLIVE2(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE2) + +#define FPUINST_ISLIVE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0) +#define FPUINST_LASTUSE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE) + +// if set, then the variable at this inst really has its upper 32 bits valid +// The difference between EEINST_LIVE1 is that the latter is used in back propagation +// The former is set at recompile time. +#define EEINST_RESETHASLIVE1(reg) { if( (reg) < 32 ) g_cpuRegHasLive1 &= ~(1<<(reg)); } +#define EEINST_HASLIVE1(reg) (g_cpuPrevRegHasLive1&(1<<(reg))) + +#define EEINST_SETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt |= (1<<(reg)); } +#define EEINST_RESETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt &= ~(1<<(reg)); } +#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg))) + +// writeback inst (used for cop2) +typedef struct _EEINSTWRITEBACK +{ + int cycle; + u32 viwrite; // mask of written viregs (REG_STATUS_FLAG and REG_MAC_FLAG are treated the same) + EEINST* parent; +} EEINSTWRITEBACK; + +void _recClearWritebacks(); +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent); + +// if cycle == -1, returns the next writeback (used for flushing) +EEINSTWRITEBACK* _recCheckWriteBack(int cycle); + +extern u32 g_recWriteback; // used for jumps +extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1; +extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt; + +extern u16 x86FpuState, iCWstate; +extern u8 g_globalMMXSaved, g_globalXMMSaved; +extern _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS]; +extern _xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalXMMLocked; +#endif + +// allocates only if later insts use XMM, otherwise checks +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode); +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode); +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode); + +// op = 0, and +// op = 1, or +// op = 2, xor +// op = 3, nor (the 32bit versoins only do OR) +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoM(u32 to, u32 from, int op); + +// 0 - ee, 1 - iop +void AddBaseBlockEx(BASEBLOCKEX*, int cpu); +void RemoveBaseBlockEx(BASEBLOCKEX*, int cpu); +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu); +void ResetBaseBlockEx(int cpu); + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu); + +#endif \ No newline at end of file diff --git a/x86/iFPU.c b/x86/iFPU.c new file mode 100644 index 0000000000..8e94d0e8d6 --- /dev/null +++ b/x86/iFPU.c @@ -0,0 +1,1364 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iFPU.h" + +#define REC_FPUBRANCH(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)f); \ + branch = 2; \ +} + +#define REC_FPUFUNC(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)f); \ +} + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +extern u32 g_minvals[4], g_maxvals[4]; + +void SetQFromStack(u32 mem) +{ + write16(0xe5d9); + FNSTSWtoAX(); + write8(0x9e); + j8Ptr[0] = JAE8(0); // jnc + + // sign bit is in bit 9 of EAX + FSTP(0); // pop + AND32ItoR(EAX, 0x200); + SHL32ItoR(EAX, 22); + OR32MtoR(EAX, (u32)&g_maxvals[0]); + MOV32RtoM(mem, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + // just pop + FSTP32(mem); + x86SetJ8(j8Ptr[1]); +} + +//////////////////////////////////////////////////// +void recMFC1(void) { + int regt, regs; + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + if( regs >= 0 ) { + _deleteGPRtoXMMreg(_Rt_, 2); + regt = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + + if( regt >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regt, regs); + + if(EEINST_ISLIVE1(_Rt_)) _signExtendGPRtoMMX(regt, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + if(EEINST_ISLIVE1(_Rt_)) { + _signExtendXMMtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs); + } + } + } + else if( (regs = _checkMMXreg(MMX_FPU+_Fs_, MODE_READ)) >= 0 ) { + // convert to mmx reg + mmxregs[regs].reg = MMX_GPR+_Rt_; + mmxregs[regs].mode |= MODE_READ|MODE_WRITE; + _signExtendGPRtoMMX(regs, _Rt_, 0); + } + else { + regt = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } + + _deleteEEreg(MMX_GPR+_Rt_, 0); + + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCFC1(void) +{ + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + MOV32MtoR( EAX, (u32)&fpuRegs.fprc[ _Fs_ ] ); + _deleteEEreg(_Rt_, 0); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } +} + +//////////////////////////////////////////////////// +void recMTC1(void) +{ + if( GPR_IS_CONST1(_Rt_) ) { + _deleteFPtoXMMreg(_Fs_, 0); + MOV32ItoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + if( g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE ) { + // transfer the reg directly + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteFPtoXMMreg(_Fs_, 2); + _allocFPtoXMMreg(mmreg, _Fs_, MODE_WRITE); + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) SSE_MOVSS_XMM_to_XMM(mmreg2, mmreg); + else SSE_MOVSS_XMM_to_M32((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + + if( cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(mmreg2, mmreg); + } + else { + SetMMXstate(); + MOVDMMXtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + _deleteFPtoXMMreg(_Fs_, 0); + SetMMXstate(); + MOVDMMXtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + + if( mmreg2 >= 0 ) SSE_MOVSS_M32_to_XMM(mmreg2, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + MOV32RtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, EAX); + } + } + } +} + +//////////////////////////////////////////////////// +void recCTC1( void ) +{ + if( GPR_IS_CONST1(_Rt_)) { + MOV32ItoM((u32)&fpuRegs.fprc[ _Fs_ ], g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + SSEX_MOVD_XMM_to_M32((u32)&fpuRegs.fprc[ _Fs_ ], mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&fpuRegs.fprc[ _Fs_ ], mmreg); + SetMMXstate(); + } + else { + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (u32)&fpuRegs.fprc[ _Fs_ ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCOP1_BC1() +{ + recCP1BC1[_Rt_](); +} + +static u32 _mxcsr = 0x7F80; +static u32 _mxcsrs; +static u32 fpucw = 0x007f; +static u32 fpucws = 0; + +//////////////////////////////////////////////////// +void SaveCW(int type) { + if (iCWstate & type) return; + + if (type == 2) { +// SSE_STMXCSR((u32)&_mxcsrs); +// SSE_LDMXCSR((u32)&_mxcsr); + } else { + FNSTCW( (u32)&fpucws ); + FLDCW( (u32)&fpucw ); + } + iCWstate|= type; +} + +//////////////////////////////////////////////////// +void LoadCW( void ) { + if (iCWstate == 0) return; + + if (iCWstate & 2) { + //SSE_LDMXCSR((u32)&_mxcsrs); + } + if (iCWstate & 1) { + FLDCW( (u32)&fpucws ); + } + iCWstate = 0; +} + +//////////////////////////////////////////////////// +void recCOP1_S( void ) +{ + if( !EE_FPU_REGCACHING || !cpucaps.hasStreamingSIMD2Extensions) { + _freeMMXreg(6); + _freeMMXreg(7); + } + recCP1S[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +void recCOP1_W( void ) +{ + if( !EE_FPU_REGCACHING ) { + _freeMMXreg(6); + _freeMMXreg(7); + } + recCP1W[ _Funct_ ]( ); +} + +#ifndef FPU_RECOMPILE + + +REC_FPUFUNC(ADD_S); +REC_FPUFUNC(SUB_S); +REC_FPUFUNC(MUL_S); +REC_FPUFUNC(DIV_S); +REC_FPUFUNC(SQRT_S); +REC_FPUFUNC(RSQRT_S); +REC_FPUFUNC(ABS_S); +REC_FPUFUNC(MOV_S); +REC_FPUFUNC(NEG_S); +REC_FPUFUNC(ADDA_S); +REC_FPUFUNC(SUBA_S); +REC_FPUFUNC(MULA_S); +REC_FPUFUNC(MADD_S); +REC_FPUFUNC(MSUB_S); +REC_FPUFUNC(MADDA_S); +REC_FPUFUNC(MSUBA_S); +REC_FPUFUNC(CVT_S); +REC_FPUFUNC(CVT_W); +REC_FPUFUNC(MIN_S); +REC_FPUFUNC(MAX_S); +REC_FPUBRANCH(BC1F); +REC_FPUBRANCH(BC1T); +REC_FPUBRANCH(BC1FL); +REC_FPUBRANCH(BC1TL); +REC_FPUFUNC(C_F); +REC_FPUFUNC(C_EQ); +REC_FPUFUNC(C_LE); +REC_FPUFUNC(C_LT); + +#else + +#ifdef EE_FPU_REGCACHING + +// define all FPU ops with XMM +#endif + +//////////////////////////////////////////////////// +void recC_EQ_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + j8Ptr[0] = JZ8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); +} + +void recC_EQ_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[_Fs_].f); + FCOMP32( (u32)&fpuRegs.fpr[_Ft_].f); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004000 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +FPURECOMPILE_CONSTCODE(C_EQ, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_F() +{ + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); +} + +//////////////////////////////////////////////////// +void recC_LT_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JB8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JBE8(0); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +void recC_LT_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00000100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[1] ); +} + +FPURECOMPILE_CONSTCODE(C_LT, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_LE_xmm(int info ) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JBE8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JB8(0); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +void recC_LE_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +FPURECOMPILE_CONSTCODE(C_LE, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +static void (*recComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_ADDSS_XMM_to_XMM, SSE_MULSS_XMM_to_XMM, SSE_MAXSS_XMM_to_XMM, SSE_MINSS_XMM_to_XMM }; + +static void (*recComOpM32_to_XMM[] )(x86SSERegType, u32) = { + SSE_ADDSS_M32_to_XMM, SSE_MULSS_M32_to_XMM, SSE_MAXSS_M32_to_XMM, SSE_MINSS_M32_to_XMM }; + +void recCommutativeOp(int info, int regd, int op) { + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd == EEREC_S) recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + } + break; + case PROCESS_EE_T: + if (regd == EEREC_T) recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Fs_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_T); + recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Fs_]); + } + break; + default: + if (regd == EEREC_S) { + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + else if (regd == EEREC_T) { + recComOpXMM_to_XMM[op](regd, EEREC_S); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } +} + +static void (*recNonComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_SUBSS_XMM_to_XMM, SSE_DIVSS_XMM_to_XMM }; + +static void (*recNonComOpM32_to_XMM[] )(x86SSERegType, u32) = { + SSE_SUBSS_M32_to_XMM, SSE_DIVSS_M32_to_XMM }; + +int recNonCommutativeOp(int info, int regd, int op) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd != EEREC_S) SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + break; + case PROCESS_EE_T: + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_M32_to_XMM(t0reg, (u32)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](t0reg, EEREC_T); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_M32_to_XMM(regd, (u32)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + default: + if (regd == EEREC_S) { + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } else + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + recNonComOpXMM_to_XMM[op](t0reg, regd); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } + + return regd; +} + +void recADD_S_xmm(int info) { + recCommutativeOp(info, EEREC_D, 0); +} + +void recADD_S_(int info) { + SetFPUstate(); + + SaveCW(1); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(ADD_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recSUB_S_xmm(int info) +{ + recNonCommutativeOp(info, EEREC_D, 0); +} + +void recSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(SUB_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recMUL_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 1); +} + +void recMUL_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MUL_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recDIV_S_xmm(int info) +{ + int regd = recNonCommutativeOp(info, EEREC_D, 1); + SSE_MAXSS_M32_to_XMM(regd, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(regd, (u32)&g_maxvals[0]); + +// _freeXMMreg(EEREC_D); +// MOV32MtoR(EAX, (int)&fpuRegs.fpr[_Fd_]); +// AND32ItoR(EAX, 0x7f800000); +// CMP32ItoR(EAX, 0x7f800000); +// j8Ptr[0] = JNE8(0); +// MOV32ItoM((int)&fpuRegs.fpr[_Fd_], 0); +// x86SetJ8(j8Ptr[0]); +} + +void recDIV_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + SetQFromStack( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(DIV_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +__declspec(align(16)) static u32 s_neg[4] = { 0x80000000, 0, 0, 0 }; +__declspec(align(16)) static u32 s_pos[4] = { 0x7fffffff, 0, 0, 0 }; + +void recSQRT_S_xmm(int info) +{ + if( info & PROCESS_EE_T ) { + if( CHECK_FORCEABS ) { + if( EEREC_D == EEREC_T ) SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&s_pos[0]); + SSE_ANDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( CHECK_FORCEABS ) { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + } + } +} + +void recSQRT_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(SQRT_S, XMMINFO_WRITED|XMMINFO_READT); + +void recABS_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + } + else { + if( _Fs_ == _Fd_ ) { + AND32ItoM((u32)&fpuRegs.fpr[_Fs_], 0x7fffffff); + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + xmmregs[EEREC_D].mode &= ~MODE_WRITE; + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + } + } +} + +void recABS_S_(int info) +{ + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f ); + AND32ItoR( EAX, 0x7fffffff ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +FPURECOMPILE_CONSTCODE(ABS_S, XMMINFO_WRITED|XMMINFO_READS); + +void recMOV_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } +} + +void recMOV_S_(int info) +{ + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX ); +} + +FPURECOMPILE_CONSTCODE(MOV_S, XMMINFO_WRITED|XMMINFO_READS); + +void recNEG_S_xmm(int info) { + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + + SSE_XORPS_M128_to_XMM(EEREC_D, (uptr)&s_neg[0]); +} + +void recNEG_S_(int info) +{ + MOV32MtoR( EAX,(u32)&fpuRegs.fpr[ _Fs_ ].f ); + XOR32ItoR( EAX, 0x80000000 ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +FPURECOMPILE_CONSTCODE(NEG_S, XMMINFO_WRITED|XMMINFO_READS); + +void recRSQRT_S_xmm(int info) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_RSQRTSS_M32_to_XMM(t0reg, (u32)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + + break; + case PROCESS_EE_T: + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + break; + default: + if( EEREC_D == EEREC_S ) { + int t0reg; + if( g_pCurInstInfo->regs[_Ft_]&EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + } + + SSE_RSQRTSS_XMM_to_XMM(t0reg, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + break; + } + + SSE_MAXSS_M32_to_XMM(EEREC_D, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_D, (u32)&g_maxvals[0]); +} + +void recRSQRT_S_(int info) +{ + static u32 tmp; + + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (u32)&tmp ); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (u32)&tmp ); + SetQFromStack( (u32)&fpuRegs.fpr[ _Fd_ ].f ); + +// FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); +// FSQRT( ); +// FSTP32( (u32)&tmp ); +// +// MOV32MtoR( EAX, (u32)&tmp ); +// OR32RtoR( EAX, EAX ); +// j8Ptr[ 0 ] = JE8( 0 ); +// FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); +// FDIV32( (u32)&tmp ); +// FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +// x86SetJ8( j8Ptr[ 0 ] ); +} + +FPURECOMPILE_CONSTCODE(RSQRT_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recADDA_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_ACC, 0); +} + +void recADDA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(ADDA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recSUBA_S_xmm(int info) { + recNonCommutativeOp(info, EEREC_ACC, 0); +} + +void recSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(SUBA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMULA_S_xmm(int info) { + recCommutativeOp(info, EEREC_ACC, 1); +} + +void recMULA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MULA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(u32)&fpuRegs.fpr[_Ft_]:(u32)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + SSE_MULSS_M32_to_XMM(regd, mreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + break; + default: + if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + break; + } +} + +void recMADD_S_xmm(int info) +{ + recMADDtemp(info, EEREC_D); +} + +void recMADD_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (u32)&fpuRegs.ACC.f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MADD_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDA_S_xmm(int info) +{ + recMADDtemp(info, EEREC_ACC); +} + +void recMADDA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (u32)&fpuRegs.ACC.f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MADDA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + if( !(info&PROCESS_EE_ACC)) { + int regacc = _allocFPACCtoXMMreg(-1, MODE_WRITE|MODE_READ); + info |= PROCESS_EE_SET_ACC(regacc)|PROCESS_EE_ACC; + } + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(u32)&fpuRegs.fpr[_Ft_]:(u32)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_M32_to_XMM(regd, mreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + + break; + default: + if (regd == EEREC_S) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if (regd == EEREC_T) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + break; + } +} + +void recMSUB_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_D); +} + +void recMSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.ACC.f ); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MSUB_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBA_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_ACC); +} + +void recMSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.ACC.f ); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MSUBA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recCVT_S_xmm(int info) +{ + if( !(info&PROCESS_EE_S) || (EEREC_D != EEREC_S && !(xmmregs[EEREC_S].mode&MODE_WRITE)) ) { + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + _deleteGPRtoXMMreg(_Fs_, 1); + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + } +} + +void recCVT_S_(int info) +{ + SetFPUstate(); + FILD32( (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(CVT_S, XMMINFO_WRITED|XMMINFO_READS); + +//////////////////////////////////////////////////// +void recCVT_W() +{ + int t0reg; + int regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + + if( regs >= 0 ) { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CVTTSS2SI_XMM_to_R32(EAX, regs); + } + else SSE_CVTTSS2SI_M32_to_R32(EAX, (u32)&fpuRegs.fpr[ _Fs_ ]); + + _deleteFPtoXMMreg(_Fd_, 2); + + CMP32ItoR(EAX, 0x80000000); + j8Ptr[0] = JNE8(0); + + // need to detect if reg is positive + if( regs >= 0 ) { + SSE_UCOMISS_XMM_to_XMM(regs, t0reg); + j8Ptr[2] = JB8(0); + } + else { + TEST32ItoM((u32)&fpuRegs.fpr[_Fs_], 0x80000000); + j8Ptr[2] = JNZ8(0); + } + + MOV32ItoM((u32)&fpuRegs.fpr[_Fd_], 0x7fffffff); + j8Ptr[1] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[2] ); + MOV32RtoM((u32)&fpuRegs.fpr[_Fd_], EAX); + + x86SetJ8( j8Ptr[1] ); + +// MOV32MtoR(EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f); +// MOV32RtoR(ECX, EAX); +// AND32ItoR(ECX, 0x7F800000); +// CMP32ItoR(ECX, 0x4e800000); +// j8Ptr[0] = JA8(0); +// +// // convert +// SSE_CVTTSS2SI_M32_to_R32(EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f); +// MOV32RtoM((u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX ); +// +// j8Ptr[1] = JMP8(0); +// +// x86SetJ8( j8Ptr[0] ); +// +// // check negative, eax = (eax&0x80000000)?0x80000000:0x7fffffff +// AND32ItoR(EAX, 0x80000000); +// SBB32RtoR(EAX, EAX); +// NEG32R(EAX); +// ADD32ItoR(EAX, 0x7fffffff); +// MOV32RtoM((u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX); +// +// x86SetJ8( j8Ptr[1] ); +} + +void recMAX_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 2); +} + +void recMAX_S_(int info) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MAX_S ); +} + +FPURECOMPILE_CONSTCODE(MAX_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recMIN_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 3); +} + +void recMIN_S_(int info) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MIN_S ); +} + +FPURECOMPILE_CONSTCODE(MIN_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recBC1F( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBC1T( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + //j32Ptr[1] = JMP32(0); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + //x86SetJ32(j32Ptr[1]); +} + +//////////////////////////////////////////////////// +void recBC1FL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBC1TL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif diff --git a/x86/iFPU.h b/x86/iFPU.h new file mode 100644 index 0000000000..0d94bffa27 --- /dev/null +++ b/x86/iFPU.h @@ -0,0 +1,60 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IFPU_H__ +#define __IFPU_H__ + +void recMFC1( void ); +void recCFC1( void ); +void recMTC1( void ); +void recCTC1( void ); +void recCOP1_BC1( void ); +void recCOP1_S( void ); +void recCOP1_W( void ); +void recC_EQ( void ); +void recC_F( void ); +void recC_LT( void ); +void recC_LE( void ); +void recADD_S( void ); +void recSUB_S( void ); +void recMUL_S( void ); +void recDIV_S( void ); +void recSQRT_S( void ); +void recABS_S( void ); +void recMOV_S( void ); +void recNEG_S( void ); +void recRSQRT_S( void ); +void recADDA_S( void ); +void recSUBA_S( void ); +void recMULA_S( void ); +void recMADD_S( void ); +void recMSUB_S( void ); +void recMADDA_S( void ); +void recMSUBA_S( void ); +void recCVT_S( void ); +void recCVT_W( void ); +void recMAX_S( void ); +void recMIN_S( void ); +void recBC1F( void ); +void recBC1T( void ); +void recBC1FL( void ); +void recBC1TL( void ); + +#endif + + diff --git a/x86/iMMI.c b/x86/iMMI.c new file mode 100644 index 0000000000..7db5ed42d7 --- /dev/null +++ b/x86/iMMI.c @@ -0,0 +1,3337 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* cached MMI opcodes * +* * +*********************************************************/ + +// NOTE: This code is disabled when xmm reg caching is ENABLED (instead use iMMI.c) +// This also means that every change that goes into here has to be repeated in iMMI.c and MMI.c (zerofrog) + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" + +#ifndef MMI_RECOMPILE + +REC_FUNC( PLZCW ); + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0 ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1 ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2 ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3 ); + +#endif + +REC_FUNC( PMFHL ); +REC_FUNC( PMTHL ); + +REC_FUNC( PSRLW ); +REC_FUNC( PSRLH ); + +REC_FUNC( PSRAH ); +REC_FUNC( PSRAW ); + +REC_FUNC( PSLLH ); +REC_FUNC( PSLLW ); + +#else + +void recPLZCW() +{ + int regd = -1; + int regs = 0; + + if ( ! _Rd_ ) return; + + if( GPR_IS_CONST1(_Rs_) ) { + _eeOnWriteReg(_Rd_, 0); + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + + for(regs = 0; regs < 2; ++regs) { + u32 val = g_cpuConstRegs[_Rs_].UL[regs]; + + if( val != 0 ) { + u32 setbit = val&0x80000000; + g_cpuConstRegs[_Rd_].UL[regs] = 0; + val <<= 1; + + while((val & 0x80000000) == setbit) { + g_cpuConstRegs[_Rd_].UL[regs]++; + val <<= 1; + } + } + else { + g_cpuConstRegs[_Rd_].UL[regs] = 31; + } + } + return; + } + + _eeOnWriteReg(_Rd_, 0); + + if( (regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE2_MOVD_XMM_to_R(EAX, regs); + regs |= MEM_XMMTAG; + } + else if( (regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVD32MMXtoR(EAX, regs); + SetMMXstate(); + regs |= MEM_MMXTAG; + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + regs = 0; + } + + if( EEINST_ISLIVE1(_Rd_) ) + _deleteEEreg(_Rd_, 0); + else { + if( (regd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) < 0 ) { + _deleteEEreg(_Rd_, 0); + } + } + + // first word + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32ItoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 31); + } + else { + SetMMXstate(); + PCMPEQDRtoR(regd, regd); + PSRLQItoR(regd, 59); + } + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32RtoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + else { + SetMMXstate(); + MOVD32RtoMMX(regd, ECX); + } + + x86SetJ8(j8Ptr[1]); + + // second word + if( EEINST_ISLIVE1(_Rd_) ) { + if( regs >= 0 && (regs & MEM_XMMTAG) ) { + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + SSE2_MOVD_XMM_to_R(EAX, regs&0xf); + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + } + else if( regs >= 0 && (regs & MEM_MMXTAG) ) { + PSHUFWRtoR(regs, regs, 0x4e); + MOVD32MMXtoR(EAX, regs&0xf); + PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e); + SetMMXstate(); + } + else MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + MOV32ItoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 31); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX); + x86SetJ8(j8Ptr[1]); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + + GPR_DEL_CONST(_Rd_); +} + +__declspec(align(16)) static u32 s_CmpMasks[] = { + 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPMFHL() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI) + + int t0reg; + + switch (_Sa_) { + case 0x00: // LW + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + break; + + case 0x01: // UW + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0xdd); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0xdd); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x02: // SLW + // fall to interp + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + iFlushCall(FLUSH_CACHED_REGS); // since calling CALLFunc + CALLFunc( (u32)PMFHL ); + break; + + case 0x03: // LH + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x04: // SH + if( EEREC_D == EEREC_HI ) { + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x72); + } + else { + if( EEREC_D != EEREC_LO ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_HI); + + // shuffle so a1a0b1b0->a1b1a0b0 + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); + } + break; + default: + SysPrintf("PMFHL??\n"); + assert(0); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMFHL, _Rd_ ); +} + +void recPMTHL() +{ + SysPrintf("PMTHL email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PMTHL, 0 ); +} + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0, _Rd_ ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1, _Rd_ ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2, _Rd_ ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3, _Rd_ ); + +#endif + +#define MMX_ALLOC_TEMP1(code) { \ + int t0reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ +} \ + +#define MMX_ALLOC_TEMP2(code) { \ + int t0reg, t1reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ +} \ + +#define MMX_ALLOC_TEMP3(code) { \ + int t0reg, t1reg, t2reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ +} \ + +#define MMX_ALLOC_TEMP4(code) { \ + int t0reg, t1reg, t2reg, t3reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t3reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ + _freeMMXreg(t3reg); \ +} \ + +//////////////////////////////////////////////////// +void recPSRLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLWItoR( t0reg, _Sa_&0xf ); + PSRLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRLW( void ) +{ + if( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLDItoR( t0reg, _Sa_ ); + PSRLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRAWItoR( t0reg, _Sa_&0xf ); + PSRAWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRADItoR( t0reg, _Sa_ ); + PSRADItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLWItoR( t0reg, _Sa_&0xf ); + PSLLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLDItoR( t0reg, _Sa_ ); + PSLLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +/* +void recMADD( void ) +{ +} + +void recMADDU( void ) +{ +} + +void recPLZCW( void ) +{ +} +*/ + +#ifdef MMI0_RECOMPILE + +void recMMI0( void ) +{ + recMMI0t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI1_RECOMPILE + +void recMMI1( void ) +{ + recMMI1t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI2_RECOMPILE + +void recMMI2( void ) +{ + recMMI2t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI3_RECOMPILE + +void recMMI3( void ) +{ + recMMI3t[ _Sa_ ]( ); +} + +#endif + +#endif + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ +#ifndef MMI0_RECOMPILE + +REC_FUNC( PADDB, _Rd_); +REC_FUNC( PADDH, _Rd_); +REC_FUNC( PADDW, _Rd_); +REC_FUNC( PADDSB, _Rd_); +REC_FUNC( PADDSH, _Rd_); +REC_FUNC( PADDSW, _Rd_); +REC_FUNC( PSUBB, _Rd_); +REC_FUNC( PSUBH, _Rd_); +REC_FUNC( PSUBW, _Rd_); +REC_FUNC( PSUBSB, _Rd_); +REC_FUNC( PSUBSH, _Rd_); +REC_FUNC( PSUBSW, _Rd_); + +REC_FUNC( PMAXW, _Rd_); +REC_FUNC( PMAXH, _Rd_); + +REC_FUNC( PCGTW, _Rd_); +REC_FUNC( PCGTH, _Rd_); +REC_FUNC( PCGTB, _Rd_); + +REC_FUNC( PEXTLW, _Rd_); + +REC_FUNC( PPACW, _Rd_); +REC_FUNC( PEXTLH, _Rd_); +REC_FUNC( PPACH, _Rd_); +REC_FUNC( PEXTLB, _Rd_); +REC_FUNC( PPACB, _Rd_); +REC_FUNC( PEXT5, _Rd_); +REC_FUNC( PPAC5, _Rd_); + +#else + +//////////////////////////////////////////////////// +void recPMAXW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMAXW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPACW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(((_Rs_!=0||!cpucaps.hasStreamingSIMD2Extensions)?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_T, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + + // swap mmx regs.. don't ask + xmmregs[t0reg] = xmmregs[EEREC_D]; + xmmregs[EEREC_D].inuse = 0; + } + } + } + else { + if( EEREC_D != EEREC_S ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x88 ); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x88 ); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); //Copy this one cos it could get overwritten + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], ECX); //This is where we bring it back + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +void recPPACH( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, t0reg, 0x88); + } + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[6]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[4]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +//////////////////////////////////////////////////// +void recPPACB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, EEREC_D); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(t0reg, 8); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(t0reg, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PPACB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXT5() +{ + SysPrintf("PEXT5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PEXT5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPAC5() +{ + SysPrintf("PPAC5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PPAC5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMAXH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + SSE_PMAXSW_MM_to_MM( t0reg, t1reg ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMAXSW_MM_to_MM( t2reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PCMPGTBRtoR( t0reg, t1reg ); + + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPGTBRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTWRtoR( t0reg, t1reg ); + PCMPGTWRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTW( void ) +{ + //TODO:optimize RS | RT== 0 + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTDRtoR( t0reg, t1reg ); + PCMPGTDRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSBRtoR( t0reg, t2reg); + PADDSBRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSWRtoR( t0reg, t2reg); + PADDSWRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + + //SysPrintf("PADDSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PADDSW ); +} + +//////////////////////////////////////////////////// +void recPSUBSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSBRtoR( t0reg, t2reg); + PSUBSBRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSWRtoR( t0reg, t2reg); + PSUBSWRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + //SysPrintf("PSUBSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PSUBSW ); +} + +//////////////////////////////////////////////////// +void recPADDB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDBRtoR( t0reg, t2reg ); + PADDBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDWRtoR( t0reg, t2reg ); + PADDWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDDRtoR( t0reg, t2reg ); + PADDDRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBBRtoR( t0reg, t2reg ); + PSUBBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBWRtoR( t0reg, t2reg ); + PSUBWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBDRtoR( t0reg, t2reg); + PSUBDRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPEXTLW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); +} + +void recPEXTLB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + //SysPrintf("PEXTLB\n"); + //Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[7]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[7]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[6]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[6]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[5]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[5]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[4]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[4]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[3]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[3]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[2]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[2]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[1]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[1]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[0]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[0]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); +} + +void recPEXTLH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[3]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[3]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[1]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +#endif + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ +#ifndef MMI1_RECOMPILE + +REC_FUNC( PABSW, _Rd_); +REC_FUNC( PABSH, _Rd_); + +REC_FUNC( PMINW, _Rd_); +REC_FUNC( PADSBH, _Rd_); +REC_FUNC( PMINH, _Rd_); +REC_FUNC( PCEQB, _Rd_); +REC_FUNC( PCEQH, _Rd_); +REC_FUNC( PCEQW, _Rd_); + +REC_FUNC( PADDUB, _Rd_); +REC_FUNC( PADDUH, _Rd_); +REC_FUNC( PADDUW, _Rd_); + +REC_FUNC( PSUBUB, _Rd_); +REC_FUNC( PSUBUH, _Rd_); +REC_FUNC( PSUBUW, _Rd_); + +REC_FUNC( PEXTUW, _Rd_); +REC_FUNC( PEXTUH, _Rd_); +REC_FUNC( PEXTUB, _Rd_); +REC_FUNC( QFSRV, _Rd_); + +#else + +//////////////////////////////////////////////////// +__declspec(align(16)) int s_MaskHighBitD[4] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; +__declspec(align(16)) int s_MaskHighBitW[4] = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 }; + +void recPABSW() +{ + if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPABSH() +{ +if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(t0reg, 15); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPMINW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_S); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMINW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPADSBH() +{ + SysPrintf("PADSBH email zero if abnormal behavior\n"); + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_D); + // reset lower bits to 0s + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 8); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + } + + // t0reg - adds, EEREC_D - subs + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE(PADSBH, _Rd_); +} + +//////////////////////////////////////////////////// +void recPADDUW() +{ +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rt_ == 0 ) { + if( _Rs_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( _Rs_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + int t2reg = _allocTempXMMreg(XMMT_INT, -1); + + if( _hasFreeXMMreg() ) { + int t3reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t3reg, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(t1reg, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t2reg, t0reg); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t3reg, t0reg); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t3reg); + _freeXMMreg(t3reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSE2_PSRLDQ_I8_to_XMM(t2reg, 8); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xE8); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t0reg); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + } + + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t1reg); + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, t2reg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t2reg); + SSE2_PCMPGTD_XMM_to_XMM(t1reg, t0reg); + SSEX_POR_XMM_to_XMM(EEREC_D, t1reg); + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + } + +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUW() +{ + SysPrintf("PSUBUW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSUBUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXTUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXTUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recQFSRV() +{ + u8* pshift1, *pshift2, *poldptr, *pnewptr; + + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + + poldptr = x86Ptr; + x86Ptr += 6; + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 0); + pshift1 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((u32)pshift1, EAX); + x86Ptr = pnewptr; + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + MOV32ItoR(ECX, 16); + SUB32RtoR(ECX, EAX); + + poldptr = x86Ptr; + x86Ptr += 12; + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 0); + pshift1 = x86Ptr-1; + + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 0); + pshift2 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((u32)pshift1, EAX); + MOV8RtoM((u32)pshift2, ECX); + + x86Ptr = pnewptr; + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( QFSRV, _Rd_ ); +} + + +void recPEXTUB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but faster than int + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[8]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[8]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[9]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[9]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[10]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[10]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[11]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[11]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[12]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[12]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[13]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[13]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[14]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[14]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[15]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[15]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); +} + +//////////////////////////////////////////////////// +void recPEXTUW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 2 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 2 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 3 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 3 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); +} + +//////////////////////////////////////////////////// +void recPMINH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMINSW_MM_to_MM( t0reg, t2reg ); + SSE_PMINSW_MM_to_MM( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQBRtoR( t0reg, t2reg ); + PCMPEQBRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQWRtoR( t0reg, t2reg ); + PCMPEQWRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t0reg, t2reg ); + PCMPEQDRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rt_ ) { + if( EEREC_D == EEREC_S ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( EEREC_D != EEREC_S ) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSBRtoR( t0reg, t2reg ); + PADDUSBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSWRtoR( t0reg, t2reg ); + PADDUSWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +#endif +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ +#ifndef MMI2_RECOMPILE + +REC_FUNC( PMFHI, _Rd_); +REC_FUNC( PMFLO, _Rd_); +REC_FUNC( PCPYLD, _Rd_); +REC_FUNC( PAND, _Rd_); +REC_FUNC( PXOR, _Rd_); + +REC_FUNC( PMADDW, _Rd_); +REC_FUNC( PSLLVW, _Rd_); +REC_FUNC( PSRLVW, _Rd_); +REC_FUNC( PMSUBW, _Rd_); +REC_FUNC( PINTH, _Rd_); +REC_FUNC( PMULTW, _Rd_); +REC_FUNC( PDIVW, _Rd_); +REC_FUNC( PMADDH, _Rd_); +REC_FUNC( PHMADH, _Rd_); +REC_FUNC( PMSUBH, _Rd_); +REC_FUNC( PHMSBH, _Rd_); +REC_FUNC( PEXEH, _Rd_); +REC_FUNC( PREVH, _Rd_); +REC_FUNC( PMULTH, _Rd_); +REC_FUNC( PDIVBW, _Rd_); +REC_FUNC( PEXEW, _Rd_); +REC_FUNC( PROT3W, _Rd_ ); + +#else + +//////////////////////////////////////////////////// +void recPMADDW() +{ + SysPrintf("PMADDW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMADDW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSLLVW() +{ + SysPrintf("PSLLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSLLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSRLVW() +{ + SysPrintf("PSRLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSRLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBW() +{ + SysPrintf("PMSUBW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) +// int t0reg = _allocTempXMMreg(XMMT_INT, -1); +// +// if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); +// else { +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); +// SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// } +// +// // add from LO/HI +// SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSUBQ_XMM_to_XMM(EEREC_LO, EEREC_D); +// +// // get the signs +// SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +// SSE2_PSRAD_I8_to_XMM(t0reg, 31); +// +// // interleave +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); +// +// SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); +// SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); +// +// _freeXMMreg(t0reg); +//CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTW() +{ + SysPrintf("PMULTW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMULTW, _Rd_ ); +} +//////////////////////////////////////////////////// +void recPDIVW() +{ + SysPrintf("PDIVW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + REC_FUNC_INLINE( PDIVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPDIVBW() +{ + SysPrintf("PDIVBW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PDIVBW, _Rd_ ); //-- +} + +//////////////////////////////////////////////////// +void recPHMADH() +{ + SysPrintf("PHMADH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _Rd_ ? EEREC_D : _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + if( !_Rd_ ) _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMADH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBH() +{ + SysPrintf("PMSUBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPHMSBH() +{ + SysPrintf("PHMSBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMSBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXEH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xc6); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPREVH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x17); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x17); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PREVH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPINTH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_MOVHLPS_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction + MOV16MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[2], EBX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[4], ECX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[0], EDX); + + MOV16MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[5]); + MOV16MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rs_].US[7]); + MOV16MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].US[3]); + + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[5], EBX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[7], ECX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[6], EDX); +} + +void recPEXEW( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPROT3W( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc9); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPMULTH( void ) +{ +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_HI, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_LO, EEREC_HI); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(t0reg, EEREC_HI); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, t0reg, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_HI); + } + + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_LO, t0reg); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(!_Rt_ || !_Rs_) { + MOV32ItoM( (u32)&cpuRegs.LO.UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[3], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[3], 0); + + if( _Rd_ ) { + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], 0); + } + return; + } + + //Done - Refraction + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[3], EAX); + + if (_Rd_) { + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +void recPMFHI( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_HI); +CPU_SSE_XMMCACHE_END + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.HI.UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.HI.UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMFLO( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.LO.UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.LO.UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPAND( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PANDMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PANDMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPXOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PXORMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PXORMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYLD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READS)|XMMINFO_READT) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_S == EEREC_T ) SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + else if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + else { + if( EEREC_D == EEREC_T ) SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x44); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t1reg ); + SetMMXstate(); + ) +} + + +void recPMADDH( void ) +{ +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PADDD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(_Rt_ && _Rs_){ + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[3], EAX); + + } + + if (_Rd_) { + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +#endif +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ +#ifndef MMI3_RECOMPILE + +REC_FUNC( PMADDUW, _Rd_); +REC_FUNC( PSRAVW, _Rd_); +REC_FUNC( PMTHI, _Rd_); +REC_FUNC( PMTLO, _Rd_); +REC_FUNC( PINTEH, _Rd_); +REC_FUNC( PMULTUW, _Rd_); +REC_FUNC( PDIVUW, _Rd_); +REC_FUNC( PCPYUD, _Rd_); +REC_FUNC( POR, _Rd_); +REC_FUNC( PNOR, _Rd_); +REC_FUNC( PCPYH, _Rd_); +REC_FUNC( PEXCW, _Rd_); +REC_FUNC( PEXCH, _Rd_); + +#else + +//////////////////////////////////////////////////// +REC_FUNC( PSRAVW, _Rd_ ); + +//////////////////////////////////////////////////// +__declspec(align(16)) u32 s_tempPINTEH[4] = {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPINTEH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + int t0reg = -1; + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PAND_M128_to_XMM(EEREC_D, (u32)s_tempPINTEH); + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_S, 0xa0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xa0); + } + else if( EEREC_D == EEREC_T ) { + assert( EEREC_D != EEREC_S ); + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_S) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSRLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + } + + if( t0reg >= 0 ) _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PINTEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTUW() +{ + SysPrintf("PMULTUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PMULTUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMADDUW() +{ + SysPrintf("PMADDUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // add from LO/HI + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + SSE2_PADDQ_XMM_to_XMM(EEREC_D, EEREC_LO); + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +//do EEINST_SETSIGNEXT +REC_FUNC( PDIVUW, _Rd_ ); + +//////////////////////////////////////////////////// +void recPEXCW() +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXCH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPNOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + } + else { + if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + if( _Rt_ != 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + if( EEREC_D == EEREC_S ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + if( EEREC_S != EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg ); + SSEX_PXOR_XMM_to_XMM( EEREC_D, t0reg ); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP3( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PORMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t2reg, t2reg ); + PXORRtoR( t0reg, t2reg ); + PXORRtoR( t1reg, t2reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTHI( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITEHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_HI, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTLO( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITELO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_LO, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYUD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READT)|XMMINFO_WRITED) + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + } + else { + if( EEREC_D == EEREC_S ) SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + //TODO + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0xee); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + } + else { + if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0xee); + } + else if( EEREC_D == EEREC_T ) { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( _Rs_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + else if( _Rt_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + if( EEREC_S != EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + if ( _Rt_ != 0 ) + { + PORMtoR ( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR ( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + } + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //PUSH32R( EBX ); + MOVZX32M16toR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOV32RtoR( ECX, EAX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EAX, ECX ); + MOVZX32M16toR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOV32RtoR( ECX, EDX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EDX, ECX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], EDX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EDX ); + //POP32R( EBX ); +} + +#endif \ No newline at end of file diff --git a/x86/iMMI.h b/x86/iMMI.h new file mode 100644 index 0000000000..c69b6bc702 --- /dev/null +++ b/x86/iMMI.h @@ -0,0 +1,133 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ +#ifndef __IMMI_H__ +#define __IMMI_H__ + +void recMADD(); +void recMADDU(); +void recPLZCW(); +void recMMI0(); +void recMMI1(); +void recMMI2(); +void recMMI3(); +void recMADD1(); +void recMADDU1(); +void recPMFHL(); +void recPMTHL(); +void recPMAXW(); +void recPMINW(); +void recPPACW(); +void recPEXTLH(); +void recPPACH(); +void recPEXTLB(); +void recPPACB(); +void recPEXT5(); +void recPPAC5(); +void recPABSW(); +void recPADSBH(); +void recPABSH(); +void recPADDUW(); +void recPSUBUW(); +void recPSUBUH(); +void recPEXTUH(); +void recPSUBUB(); +void recPEXTUB(); +void recQFSRV(); +void recPMADDW(); +void recPSLLVW(); +void recPSRLVW(); +void recPMSUBW(); +void recPINTH(); +void recPMULTW(); +void recPDIVW(); +void recPMADDH(); +void recPHMADH(); +void recPMSUBH(); +void recPHMSBH(); +void recPEXEH(); +void recPREVH(); +void recPMULTH(); +void recPDIVBW(); +void recPEXEW(); +void recPROT3W(); +void recPMADDUW(); +void recPSRAVW(); +void recPINTEH(); +void recPMULTUW(); +void recPDIVUW(); +void recPEXCH(); +void recPEXCW(); + +void recPSRLH(); +void recPSRLW(); +void recPSRAH(); +void recPSRAW(); +void recPSLLH(); +void recPSLLW(); +void recMTHI1(); +void recMTLO1(); +void recMFHI1(); +void recMFLO1(); +void recMULT1(); +void recMULTU1(); +void recDIV1(); +void recDIVU1(); +void recPMAXH(); +void recPCGTB(); +void recPCGTH(); +void recPCGTW(); +void recPADDSB(); +void recPADDSH(); +void recPADDSW(); +void recPSUBSB(); +void recPSUBSH(); +void recPSUBSW(); +void recPADDB(); +void recPADDH(); +void recPADDW(); +void recPSUBB(); +void recPSUBH(); +void recPSUBW(); +void recPEXTLW(); +void recPEXTUW(); +void recPMINH(); +void recPCEQB(); +void recPCEQH(); +void recPCEQW(); +void recPADDUB(); +void recPADDUH(); +void recPMFHI(); +void recPMFLO(); +void recPAND(); +void recPXOR(); +void recPCPYLD(); +void recPNOR(); +void recPMTHI(); +void recPMTLO(); +void recPCPYUD(); +void recPOR(); +void recPCPYH(); + +#endif + + diff --git a/x86/iR3000A.cpp b/x86/iR3000A.cpp new file mode 100644 index 0000000000..6adb37e993 --- /dev/null +++ b/x86/iR3000A.cpp @@ -0,0 +1,1371 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking Jan06 +// and added reg caching, const propagation, block analysis Jun06 +// zerofrog(@gmail.com) + +#if 1 + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "zlib.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "ir3000A.h" +#include "PsxCounters.h" + +extern u32 psxNextCounter, psxNextsCounter; +u32 g_psxMaxRecMem = 0; +extern char *disRNameGPR[]; +extern char* disR3000Fasm(u32 code, u32 pc); +} + +#define PSX_NUMBLOCKS (1<<12) +#define MAPBASE 0x48000000 +#define RECMEM_SIZE (8*1024*1024) + +// R3000A statics +uptr *psxRecLUT; +int psxreclog = 0; + +static u32 s_BranchCount = 0; +static char *recMem; // the recompiled blocks will be here +static BASEBLOCK *recRAM; // and the ptr to the blocks here +static BASEBLOCK *recROM; // and here +static BASEBLOCK *recROM1; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr; +u32 psxpc; // recompiler psxpc +int psxbranch; // set for branch +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_psxNextBranchCycle = 0; + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what psxpc the current block ends + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +static u32 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_psxBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch); +void psxRecompileNextInstruction(int delayslot); +static void recRecompile(u32 startpc); + +extern void (*rpsxBSC[64])(); +extern void (*rpsxBSC_co[64])(); +void rpsxpropBSC(EEINST* prev, EEINST* pinst); + +#ifdef _DEBUG +extern "C" u32 psxdump = 0; +#else +#define psxdump 0 +#endif + +#define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) + +#define PSXREC_CLEARM(mem) { \ + if ((mem) < g_psxMaxRecMem && psxRecLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PSX_GETBLOCK(mem); \ + if( *(u32*)p ) psxRecClearMem(p); \ + } \ +} \ + +BASEBLOCKEX* PSX_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+PSX_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 1); +} + +//////////////////////////////////////////////////// +static void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + u8 used[34]; + int numused, count; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, psxpc, psxRegs.cycle ); +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); +sprintf( filename, "dumps\\psxdump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/psxdump%.8X.txt", startpc); +#endif + + fflush( stdout ); + + f = fopen( filename, "w" ); + assert( f != NULL ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR3000Fasm( *(u32*)PSXM( i ), i ) ); + } + + // write the instruction info + fprintf(f, "\n\nlive0 - %x, lastuse - %x used - %x\n", EEINST_LIVE0, EEINST_LASTUSE, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&count>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _psxIsLoadStore(u32 tempcode) +{ + switch(tempcode>>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + return 1; + } + return 0; +} + +void _psxFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( psxpc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && PSX_IS_CONST1(i) ) _psxFlushConstReg(i); + else { + _deleteX86reg(X86TYPE_PSX, i, 1); + } + } +} + +int _psxFlushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_psxHasConstReg & (1< 0 ); + + // make sure right GPR was saved + assert( g_psxHasConstReg == s_saveHasConstReg || (g_psxHasConstReg ^ s_saveHasConstReg) == (1< 0) { + pblock = PSX_GETBLOCK(psxRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != psxRegs.pc ) { + recRecompile(psxRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + +#ifdef _DEBUG + + fnptr = (u8*)pblock->pFnptr; + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + pfn = ((R3000AFNPTR)pblock->pFnptr); + // use call instead of pfn() + __asm call pfn +#endif + } +} + +extern u32 g_psxNextBranchCycle; +u32 g_psxlastpc = 0; +static u32 g_temp; + +// jumped to when invalid psxpc address +__declspec(naked,noreturn) void psxDispatcher() +{ + // EDX contains the current psxpc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == psxRegs.pc + mov ecx, psxRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push psxRegs.pc // psxpc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new psxpc +// and eax, 0x0fffffff +// mov ecx, psxRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void psxDispatcherClear() +{ + // EDX contains the current psxpc + __asm mov psxRegs.pc, edx + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + if( s_pDispatchBlock->startpc == psxRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable psxpc address +__declspec(naked,noreturn) void psxDispatcherReg() +{ + __asm { + //s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + mov edx, psxRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, psxRecLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == psxRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +static void recClear(u32 Addr, u32 Size) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + PSXREC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void rpsxMemConstClear(u32 mem) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !psxRecLUT[mem>>16] ) + return; + + CMP32ItoM((u32)PSX_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PSX_GETBLOCK(mem)); + CALLFunc((u32)psxRecClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); +} + +void psxRecClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms + if (cpucaps.has3DNOWInstructionExtensions) __asm femms + else __asm emms + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + psxRecClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)psxDispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PSX_GETBLOCK(p->startpc); + pexblock = PSX_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 1); + pexblock->size = 0; + pexblock->startpc = 0; +} + +void psxSetBranchReg(u32 reg) +{ + psxbranch = 1; + + if( reg != 0xffffffff ) { + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, reg); + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&psxRegs.pc, EAX); + } + } + + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(0xffffffff, 1); + + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void psxSetBranchImm( u32 imm ) +{ + u32* ptr; + psxbranch = 1; + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&psxRegs.pc, imm ); + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(imm, imm <= psxpc); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)psxDispatcher - ( (u32)x86Ptr + 5 )); +} + +#define USE_FAST_BRANCHES 0 + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch) +{ + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&psxRegs.cycle); + ADD32ItoR(ECX, s_psxBlockCycles*17/16); // greater mult factor causes nfsmw to crash + MOV32RtoM((int)&psxRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&psxRegs.cycle, s_psxBlockCycles*17/16); + return; + } + + SUB32MtoR(ECX, (int)&g_psxNextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + CALLFunc((int)psxBranchTest); + + CMP32ItoM((int)&EEsCycle, 0); + j8Ptr[2] = JG8(0); + RET2(); + x86SetJ8( j8Ptr[2] ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&psxRegs.pc, newpc); + JNE32((u32)psxDispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + +static int *s_pCode; + +static void checkcodefn() +{ + int pctemp; + + __asm mov pctemp, eax + SysPrintf("iop code changed! %x\n", pctemp); +} + +void rpsxSYSCALL() +{ + MOV32ItoM( (u32)&psxRegs.code, psxRegs.code ); + MOV32ItoM((uptr)&psxRegs.pc, psxpc - 4); + _psxFlushCall(FLUSH_NODESTROY); + + PUSH32I(psxbranch == 1 ? 1 : 0); + PUSH32I(0x20); + CALLFunc ((int)psxException); + ADD32ItoR(ESP, 8); + + CMP32ItoM((int)&psxRegs.pc, psxpc-4); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&psxRegs.cycle, s_psxBlockCycles); + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + + //if (!psxbranch) psxbranch = 2; +} + +u32 psxRecompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PSX_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( psxpc == pblock->startpc ) + return 0; + } + + return 1; +} + +void psxRecompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + + BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && psxpc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&psxRegs.pc, psxpc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + psxbranch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == psxpc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + psxRecClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", psxpc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSXM( psxpc ); + assert(s_pCode); + + psxRegs.code = *(int *)s_pCode; + s_psxBlockCycles++; + psxpc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, psxRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, psxpc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +//#endif + + g_pCurInstInfo++; + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + assert(0); +// recBSC_co[cpuRegs.code>>26](); +// psxpc += 4; +// s_psxBlockCycles++; +// g_pCurInstInfo++; + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + rpsxBSC[ psxRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //_psxFlushUnusedConstReg(); + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + _clearNeededX86regs(); +} + +static void recExecute() { + for (;;) execute(); +} + +static void recExecuteBlock() { + + execute(); +} + +extern "C" +void iDumpPsxRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + + __Log("%spsxreg: %x %x\n", pstr, startpc, psxRegs.interrupt); + for(i = 0; i < 34; i+=2) __Log("%spsx%d: %x %x\n", pstr, i, psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]); + __Log("%scycle: %x %x %x %x; counters %x %x\n", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle, IOPoCycle, + (u32)psxNextsCounter, (u32)psxNextCounter); + + for(i = 0; i < 6; ++i) __Log("%scounter%d: %x %x %x\n", pstr, i, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT); + for(i = 0; i < 32; ++i) { + __Log("int%d: %x %x\n", i, psxRegs.sCycle[i], psxRegs.eCycle[i]); + } +} + +void iDumpPsxRegisters(u32 startpc); + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0; + const int skip = 0; + + if( (psxdump&2) ) {//&& lastrec != g_psxlastpc ) { + curcount++; + + if( curcount > skip ) { + iDumpPsxRegisters(g_psxlastpc, 1); + curcount = 0; + } + + lastrec = g_psxlastpc; + } +} + +u32 s_recblocks[] = {0}; + +static void recRecompile(u32 startpc) +{ + u32 i; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + +#ifdef _DEBUG + //psxdump |= 4; + if( psxdump & 4 ) + iDumpPsxRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000)) + recReset(); + + s_pCurBlock = PSX_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + psxRecClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < PSX_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%PSX_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%PSX_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%PSX_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + + psxbranch = 0; + + s_pCurBlock->startpc = startpc; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_psxBlockCycles = 0; + + // reset recomp state variables + psxpc = startpc; + s_saveConstGPRreg = 0; + g_psxHasConstReg = g_psxFlushedConstReg = 1; + + _initX86regs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_psxlastpc, psxpc); + CALLFunc((u32)printfn); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + + while(1) { + BASEBLOCK* pblock = PSX_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + psxRegs.code = *(int *)PSXM(i); + + switch(psxRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ == 0 || _Rt_ == 1 || _Rt_ == 16 || _Rt_ == 17 ) { + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + psxRegs.code = *(int *)PSXM(i-4); + pcur[-1] = pcur[0]; + rpsxpropBSC(pcur-1, pcur); + pcur--; + } + } + + // peephole optimizations // +// { +// g_pCurInstInfo = s_pInstCache; +// +// for(i = startpc; i < s_nEndBlock-4; i += 4) { +// g_pCurInstInfo++; +// if( psxRecompileCodeSafe(i) ) { +// u32 curcode = *(u32*)PSXM(i); +// u32 nextcode = *(u32*)PSXM(i+4); +// if( _psxIsLoadStore(curcode) && _psxIsLoadStore(nextcode) && (curcode>>26) == (nextcode>>26) && rpsxBSC_co[curcode>>26] != NULL ) { +// +// // rs has to be the same, and cannot be just written +// if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_psxLoadWritesRs(curcode) ) { +// +// // good enough +// g_pCurInstInfo[0].info |= EEINSTINFO_COREC; +// g_pCurInstInfo[0].numpeeps = 1; +// g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; +// g_pCurInstInfo++; +// i += 4; +// continue; +// } +// } +// } +// } +// } + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (psxdump & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + g_pCurInstInfo = s_pInstCache; + while (!psxbranch && psxpc < s_nEndBlock) { + psxRecompileNextInstruction(0); + } + + assert( (psxpc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (psxpc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 1); + + if( !(psxpc&0x10000000) ) + g_psxMaxRecMem = max( (psxpc&~0xa0000000), g_psxMaxRecMem ); + + if( psxbranch == 2 ) { + _psxFlushCall(FLUSH_EVERYTHING); + + iPsxBranchTest(0xffffffff, 1); + + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( psxbranch != 3 ); + if( psxbranch ) assert( !willbranch3 ); + else ADD32ItoM((int)&psxRegs.cycle, s_psxBlockCycles*17/16); + + if( willbranch3 ) { + BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock); + assert( psxpc == s_nEndBlock ); + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&psxRegs.pc, psxpc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + psxbranch = 3; + } + else if( !psxbranch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&psxRegs.pc, psxpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + //JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+RECMEM_SIZE ); + + recPtr = x86Ptr; + + assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); + + if( !psxbranch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PSX_GETBLOCK(psxpc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != psxpc ) + recRecompile(psxpc); + + // could have reset + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; + +#endif \ No newline at end of file diff --git a/x86/iR3000A.h b/x86/iR3000A.h new file mode 100644 index 0000000000..436162817a --- /dev/null +++ b/x86/iR3000A.h @@ -0,0 +1,99 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _R3000A_SUPERREC_ +#define _R3000A_SUPERREC_ + +extern void __Log(char *fmt, ...); + +// to be consistent with EE +#define PSX_HI MMX_HI +#define PSX_LO MMX_LO + +extern uptr *psxRecLUT; + +u8 _psxLoadWritesRs(u32 tempcode); +u8 _psxIsLoadStore(u32 tempcode); + +void _psxFlushAllUnused(); +int _psxFlushUnusedConstReg(); +void _psxFlushCachedRegs(); +void _psxFlushConstReg(int reg); +void _psxFlushConstRegs(); + +void _psxDeleteReg(int reg, int flush); +void _psxFlushCall(int flushtype); + +void _psxOnWriteReg(int reg); +void PSX_CHECK_SAVE_REG(int reg); + +extern u32 psxpc; // recompiler pc +extern int psxbranch; // set for branch + +void psxSaveBranchState(); +void psxLoadBranchState(); + +void psxSetBranchReg(u32 reg); +void psxSetBranchImm( u32 imm ); +void psxRecompileNextInstruction(int delayslot); + +typedef void (*R3000AFNPTR)(); +typedef void (*R3000AFNPTR_INFO)(int info); + +void psxRecClearMem(BASEBLOCK* p); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define PSXRECOMPILE_CONSTCODE0(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst0(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_); \ +} \ + +// rt = rs op imm16 +#define PSXRECOMPILE_CONSTCODE1(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst1(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// rd = rt op sa +#define PSXRECOMPILE_CONSTCODE2(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst2(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// [lo,hi] = rt op rs +#define PSXRECOMPILE_CONSTCODE3(fn, LOHI) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst3(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_, LOHI); \ +} \ + +// rd = rs op rt +void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode); +// rt = rs op imm16 +void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// rd = rt op sa +void psxRecompileCodeConst2(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// [lo,hi] = rt op rs +void psxRecompileCodeConst3(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode, int LOHI); + +#endif \ No newline at end of file diff --git a/x86/iR3000Atables.cpp b/x86/iR3000Atables.cpp new file mode 100644 index 0000000000..ed898ecaec --- /dev/null +++ b/x86/iR3000Atables.cpp @@ -0,0 +1,2054 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if 1 + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "ir3000A.h" + +extern void psxLWL(); +extern void psxLWR(); +extern void psxSWL(); +extern void psxSWR(); + +extern int g_psxWriteOk; +extern u32 g_psxMaxRecMem; +} + +// R3000A instruction implementation +#define REC_FUNC(f) \ +void psx##f(); \ +static void rpsx##f() { \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + _psxFlushCall(FLUSH_EVERYTHING); \ + /*MOV32ItoM((u32)&psxRegs.pc, (u32)pc);*/ \ + CALLFunc((u32)psx##f); \ + PSX_DEL_CONST(_Rt_); \ +/* branch = 2; */\ +} + +//// +void rpsxADDIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] + _Imm_; +} + +// adds a constant to sreg and puts into dreg +void rpsxADDconst(int dreg, int sreg, u32 off, int info) +{ + if (sreg) { + if (sreg == dreg) { + ADD32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + if (off) ADD32ItoR(EAX, off); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } +} + +void rpsxADDIU_(int info) +{ + // Rt = Rs + Im + if (!_Rt_) return; + rpsxADDconst(_Rt_, _Rs_, _Imm_, info); +} + +PSXRECOMPILE_CONSTCODE1(ADDIU); + +void rpsxADDI() { rpsxADDIU(); } + +//// SLTI +void rpsxSLTI_const() +{ + g_psxConstRegs[_Rt_] = *(int*)&g_psxConstRegs[_Rs_] < _Imm_; +} + +void rpsxSLTconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETL8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTI_(int info) { rpsxSLTconst(info, _Rt_, _Rs_, _Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTI); + +//// SLTIU +void rpsxSLTIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] < _ImmU_; +} + +void rpsxSLTUconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETB8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTIU_(int info) { rpsxSLTUconst(info, _Rt_, _Rs_, (s32)_Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTIU); + +//// ANDI +void rpsxANDI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] & _ImmU_; +} + +void rpsxANDconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + AND32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + AND32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], 0); + } +} + +void rpsxANDI_(int info) { rpsxANDconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ANDI); + +//// ORI +void rpsxORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] | _ImmU_; +} + +void rpsxORconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + OR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + OR32ItoR (EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxORI_(int info) { rpsxORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ORI); + +void rpsxXORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] ^ _ImmU_; +} + +void rpsxXORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm == 0xffffffff ) { + if( dreg == sreg ) { + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } + else if (imm) { + + if (sreg == dreg) { + XOR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + XOR32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxXORI_(int info) { rpsxXORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(XORI); + +void rpsxLUI() +{ + if(!_Rt_) return; + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + PSX_SET_CONST(_Rt_); + g_psxConstRegs[_Rt_] = psxRegs.code << 16; +} + +void rpsxADDU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] + g_psxConstRegs[_Rt_]; +} + +void rpsxADDU_consts(int info) { rpsxADDconst(_Rd_, _Rt_, g_psxConstRegs[_Rs_], info); } +void rpsxADDU_constt(int info) +{ + info |= PROCESS_EE_SET_S(EEREC_T); + rpsxADDconst(_Rd_, _Rs_, g_psxConstRegs[_Rt_], info); +} + +void rpsxADDU_(int info) +{ + if (_Rs_ && _Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else if (_Rs_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } else if (_Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else { + XOR32RtoR(EAX, EAX); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(ADDU); + +void rpsxADD() { rpsxADDU(); } + + +void rpsxSUBU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] - g_psxConstRegs[_Rt_]; +} + +void rpsxSUBU_consts(int info) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rs_]); + SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSUBU_constt(int info) { rpsxADDconst(_Rd_, _Rs_, -(int)g_psxConstRegs[_Rt_], info); } + +void rpsxSUBU_(int info) +{ + // Rd = Rs - Rt + if (!_Rd_) return; + + if( _Rd_ == _Rs_ ) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SUB32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +PSXRECOMPILE_CONSTCODE0(SUBU); + +void rpsxSUB() { rpsxSUBU(); } + +void rpsxLogicalOp(int info, int op) +{ + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[vreg]); + LogicalOp32RtoM((u32)&psxRegs.GPR.r[_Rd_], ECX, op); + if( op == 3 ) + NOT32M((u32)&psxRegs.GPR.r[_Rd_]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + LogicalOp32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_], op); + if( op == 3 ) + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], ECX); + } +} + +void rpsxAND_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] & g_psxConstRegs[_Rt_]; +} + +void rpsxAND_consts(int info) { rpsxANDconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxAND_constt(int info) { rpsxANDconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxAND_(int info) { rpsxLogicalOp(info, 0); } + +PSXRECOMPILE_CONSTCODE0(AND); + +void rpsxOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]; +} + +void rpsxOR_consts(int info) { rpsxORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxOR_constt(int info) { rpsxORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxOR_(int info) { rpsxLogicalOp(info, 1); } + +PSXRECOMPILE_CONSTCODE0(OR); + +//// XOR +void rpsxXOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] ^ g_psxConstRegs[_Rt_]; +} + +void rpsxXOR_consts(int info) { rpsxXORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxXOR_constt(int info) { rpsxXORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxXOR_(int info) { rpsxLogicalOp(info, 2); } + +PSXRECOMPILE_CONSTCODE0(XOR); + +//// NOR +void rpsxNOR_const() +{ + g_psxConstRegs[_Rd_] = ~(g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]); +} + +void rpsxNORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm ) { + if( dreg == sreg ) { + OR32ItoM((u32)&psxRegs.GPR.r[dreg], imm); + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + OR32ItoR(ECX, imm); + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } + else { + if( dreg == sreg ) { + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxNOR_consts(int info) { rpsxNORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxNOR_constt(int info) { rpsxNORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxNOR_(int info) { rpsxLogicalOp(info, 3); } + +PSXRECOMPILE_CONSTCODE0(NOR); + +//// SLT +void rpsxSLT_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rs_] < *(int*)&g_psxConstRegs[_Rt_]; +} + +void rpsxSLT_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETG8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLT_constt(int info) { rpsxSLTconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLT_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLT); + +//// SLTU +void rpsxSLTU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] < g_psxConstRegs[_Rt_]; +} + +void rpsxSLTU_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETA8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLTU_constt(int info) { rpsxSLTUconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLTU_(int info) +{ + // Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLTU); + +//// MULT +void rpsxMULT_const() +{ + u64 res = (s64)((s64)*(int*)&g_psxConstRegs[_Rs_] * (s64)*(int*)&g_psxConstRegs[_Rt_]); + + MOV32ItoM((u32)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTsuperconst(int info, int sreg, int imm, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32ItoR(EAX, imm); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[sreg]); + else MUL32M ((uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULTsuper(int info, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + else MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULT_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 1); } +void rpsxMULT_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 1); } +void rpsxMULT_(int info) { rpsxMULTsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(MULT, 1); + +//// MULTU +void rpsxMULTU_const() +{ + u64 res = (u64)((u64)g_psxConstRegs[_Rs_] * (u64)g_psxConstRegs[_Rt_]); + + MOV32ItoM((u32)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTU_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 0); } +void rpsxMULTU_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 0); } +void rpsxMULTU_(int info) { rpsxMULTsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(MULTU, 1); + +//// DIV +void rpsxDIV_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = *(int*)&g_psxConstRegs[_Rs_] / *(int*)&g_psxConstRegs[_Rt_]; + hi = *(int*)&g_psxConstRegs[_Rs_] % *(int*)&g_psxConstRegs[_Rt_]; + MOV32ItoM((u32)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVsuperconsts(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rs_]; + + if( imm ) { + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32ItoR(EAX, imm); + CDQ(); + + if( sign ) IDIV32R (ECX); + else DIV32R(ECX); + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); + } + else { + XOR32RtoR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxDIVsuperconstt(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rt_]; + + if( imm ) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32ItoR(ECX, imm); + CDQ(); + + if( sign ) IDIV32R (ECX); + else DIV32R(ECX); + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + } +} + +void rpsxDIVsuper(int info, int sign) +{ + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); +} + +void rpsxDIV_consts(int info) { rpsxDIVsuperconsts(info, 1); } +void rpsxDIV_constt(int info) { rpsxDIVsuperconstt(info, 1); } +void rpsxDIV_(int info) { rpsxDIVsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(DIV, 1); + +//// DIVU +void rpsxDIVU_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = g_psxConstRegs[_Rs_] / g_psxConstRegs[_Rt_]; + hi = g_psxConstRegs[_Rs_] % g_psxConstRegs[_Rt_]; + MOV32ItoM((u32)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVU_consts(int info) { rpsxDIVsuperconsts(info, 0); } +void rpsxDIVU_constt(int info) { rpsxDIVsuperconstt(info, 0); } +void rpsxDIVU_(int info) { rpsxDIVsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(DIVU, 1); + +//// LoadStores +#ifdef WIN32_VIRTUAL_MEM + +// VM load store functions (fastest) + +//#define REC_SLOWREAD +//#define REC_SLOWWRITE + +int _psxPrepareReg(int gprreg) +{ + return 0; +} + +static u32 s_nAddMemOffset = 0; + +#define SET_HWLOC() { \ + x86SetJ8(j8Ptr[0]); \ + SHR32ItoR(ECX, 3); \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ +} \ + +int rpsxSetMemLocation(int regs, int mmreg) +{ + s_nAddMemOffset = 0; + MOV32MtoR( ECX, (int)&psxRegs.GPR.r[ regs ] ); + + if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); + + SHL32ItoR(ECX, 3); + j8Ptr[0] = JS8(0); + SHR32ItoR(ECX, 3); + AND32ItoR(ECX, 0x1fffff); // 2Mb + return 1; +} + +void recLoad32(u32 bit, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _psxOnWriteReg(_Rt_); + mmreg = EAX; + + switch(bit) { + case 8: ineax = psxRecMemConstRead8(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); break; + case 16: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 2 == 0 ); + ineax = psxRecMemConstRead16(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); + break; + case 32: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 4 == 0 ); + ineax = psxRecMemConstRead32(mmreg, g_psxConstRegs[_Rs_]+_Imm_); + break; + } + + if( _Rt_ ) MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)psxRecMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)psxRecMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + CALLFunc( (int)psxRecMemRead32 ); + break; + } + + x86SetJ8(j8Ptr[1]); + } + + MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } +} + +void rpsxLB() { recLoad32(8, 1); } +void rpsxLBU() { recLoad32(8, 0); } +void rpsxLH() { recLoad32(16, 1); } +void rpsxLHU() { recLoad32(16, 0); } +void rpsxLW() { recLoad32(32, 0); } + +extern void rpsxMemConstClear(u32 mem); + +// check if mem is executable, and clear it +__declspec(naked) void rpsxWriteMemClear() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, psxRecLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call psxRecClearMem + add esp, 4 +ClearRet: + ret + } +} + +extern u32 s_psxBlockCycles; +void recStore(int bit) +{ +#ifdef REC_SLOWWRITE + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + u8* pjmpok; + u32 addr = g_psxConstRegs[_Rs_]+_Imm_; + int doclear = 0; + + if( !(addr & 0x10000000) ) { + // check g_psxWriteOk + CMP32ItoM((u32)&g_psxWriteOk, 0); + pjmpok = JE8(0); + } + + switch(bit) { + case 8: + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite8(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite8(addr, EAX); + } + + break; + + case 16: + assert( (addr)%2 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite16(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite16(addr, EAX); + } + + break; + + case 32: + assert( (addr)%4 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite32(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite32(addr, EAX); + } + + break; + } + + if( !(addr & 0x10000000) ) { + if( doclear ) rpsxMemConstClear((addr)&~3); + x86SetJ8(pjmpok); + } + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + CMP32ItoM((u32)&g_psxWriteOk, 0); + u8* pjmpok = JE8(0); + + if( PSX_IS_CONST1( _Rt_ ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 16: MOV16ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 32: MOV32ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + } + } + else { + switch(bit) { + case 8: + MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV8RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 16: + MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV16RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 32: + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + } + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&g_psxMaxRecMem); + + j8Ptr[1] = JAE8(0); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + CALLFunc((u32)rpsxWriteMemClear); + + if( dohw ) { + j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( PSX_IS_CONST1(_Rt_) ) { + switch(bit) { + case 8: MOV8ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 16: MOV16ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 32: MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); break; + } + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 16: MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 32: MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + } + } + + if( s_nAddMemOffset != 0 ) ADD32ItoR(ECX, s_nAddMemOffset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)psxRecMemWrite8 ); break; + case 16: CALLFunc( (int)psxRecMemWrite16 ); break; + case 32: CALLFunc( (int)psxRecMemWrite32 ); break; + } + + x86SetJ8(j8Ptr[2]); + } + + x86SetJ8(j8Ptr[1]); + x86SetJ8(pjmpok); + } +} + +void rpsxSB() { recStore(8); } +void rpsxSH() { recStore(16); } +void rpsxSW() { recStore(32); } + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +#else + +// TLB loadstore functions (slower +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +static void rpsxLB() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead8); + if (_Rt_) { + MOVSX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLBU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead8); + if (_Rt_) { + MOVZX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLH() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead16); + if (_Rt_) { + MOVSX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLHU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead16); + if (_Rt_) { + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLW() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + + TEST32ItoR(EAX, 0x10000000); + j8Ptr[0] = JZ8(0); + + PUSH32R (EAX); + CALLFunc((int)psxMemRead32); + if (_Rt_) { + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + // read from psM directly + AND32ItoR(EAX, 0x0fffffff); + ADD32ItoR(EAX, (u32)psxM); + + MOV32RmtoR( EAX, EAX ); + MOV32RtoM( (uptr)&psxRegs.GPR.r[_Rt_], EAX); + + x86SetJ8(j8Ptr[1]); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxSB() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite8); + ADD32ItoR(ESP, 8); +} + +static void rpsxSH() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite16); + ADD32ItoR(ESP, 8); +} + +static void rpsxSW() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite32); + ADD32ItoR(ESP, 8); +} + +#endif // end load store + +//// SLL +void rpsxSLL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << _Sa_; +} + +// shifttype: 0 - sll, 1 - srl, 2 - sra +void rpsxShiftConst(int info, int rdreg, int rtreg, int imm, int shifttype) +{ + imm &= 0x1f; + if (imm) { + if( rdreg == rtreg ) { + switch(shifttype) { + case 0: SHL32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + case 1: SHR32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + case 2: SAR32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + } + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[rtreg]); + switch(shifttype) { + case 0: SHL32ItoR(EAX, imm); break; + case 1: SHR32ItoR(EAX, imm); break; + case 2: SAR32ItoR(EAX, imm); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[rdreg], EAX); + } + } + else { + if( rdreg != rtreg ) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[rtreg]); + MOV32RtoM((u32)&psxRegs.GPR.r[rdreg], EAX); + } + } +} + +void rpsxSLL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 0); } +PSXRECOMPILE_CONSTCODE2(SLL); + +//// SRL +void rpsxSRL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 1); } +PSXRECOMPILE_CONSTCODE2(SRL); + +//// SRA +void rpsxSRA_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRA_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 2); } +PSXRECOMPILE_CONSTCODE2(SRA); + +//// SLLV +void rpsxSLLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxShiftVconsts(int info, int shifttype) +{ + rpsxShiftConst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_], shifttype); +} + +void rpsxShiftVconstt(int info, int shifttype) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + switch(shifttype) { + case 0: SHL32CLtoR(EAX); break; + case 1: SHR32CLtoR(EAX); break; + case 2: SAR32CLtoR(EAX); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLLV_consts(int info) { rpsxShiftVconsts(info, 0); } +void rpsxSLLV_constt(int info) { rpsxShiftVconstt(info, 0); } +void rpsxSLLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLLV); + +//// SRLV +void rpsxSRLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRLV_consts(int info) { rpsxShiftVconsts(info, 1); } +void rpsxSRLV_constt(int info) { rpsxShiftVconstt(info, 1); } +void rpsxSRLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRLV); + +//// SRAV +void rpsxSRAV_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRAV_consts(int info) { rpsxShiftVconsts(info, 2); } +void rpsxSRAV_constt(int info) { rpsxShiftVconstt(info, 2); } +void rpsxSRAV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRAV); + +extern void rpsxSYSCALL(); + +void rpsxBREAK() { +} + +void rpsxMFHI() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTHI() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } +} + +void rpsxMFLO() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTLO() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxJ() +{ + // j target + u32 newpc = _Target_ * 4 + (psxpc & 0xf0000000); + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJAL() +{ + u32 newpc = (_Target_ << 2) + ( psxpc & 0xf0000000 ); + _psxDeleteReg(31, 0); + PSX_SET_CONST(31); + g_psxConstRegs[31] = psxpc + 4; + + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJR() +{ + psxSetBranchReg(_Rs_); +} + +void rpsxJALR() +{ + // jalr Rs + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, _Rs_); + + if ( _Rd_ ) + { + _psxDeleteReg(_Rd_, 0); + PSX_SET_CONST(_Rd_); + g_psxConstRegs[_Rd_] = psxpc + 4; + } + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&psxRegs.pc, EAX); + } + + psxSetBranchReg(0xffffffff); +} + +//// BEQ +static void* s_pbranchjmp; +static u32 s_do32 = 0; + +#define JUMPVALID(pjmp) (( x86Ptr - (s8*)pjmp ) <= 0x80) + +void rpsxSetBranchEQ(int info, int process) +{ + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&psxRegs.GPR.r[ _Rt_ ], g_psxConstRegs[_Rs_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&psxRegs.GPR.r[ _Rs_ ], g_psxConstRegs[_Rt_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else { + MOV32MtoR( EAX, (int)&psxRegs.GPR.r[ _Rs_ ] ); + CMP32MtoR( EAX, (int)&psxRegs.GPR.r[ _Rt_ ] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } +} + +void rpsxBEQ_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] == g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + } + else + { + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + psxSaveBranchState(); + + rpsxSetBranchEQ(info, process); + + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + } +} + +void rpsxBEQ_(int info) { rpsxBEQ_process(info, 0); } +void rpsxBEQ_consts(int info) { rpsxBEQ_process(info, PROCESS_CONSTS); } +void rpsxBEQ_constt(int info) { rpsxBEQ_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BEQ, 0); + +//// BNE +void rpsxBNE_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] != g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + return; + } + + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + rpsxSetBranchEQ(info, process); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +void rpsxBNE_(int info) { rpsxBNE_process(info, 0); } +void rpsxBNE_consts(int info) { rpsxBNE_process(info, PROCESS_CONSTS); } +void rpsxBNE_constt(int info) { rpsxBNE_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BNE, 0); + +//// BLTZ +void rpsxBLTZ() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZ +void rpsxBGEZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLTZAL +void rpsxBLTZAL() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + else { + PSX_SET_CONST(_Rt_); + g_psxConstRegs[31] = psxpc+4; + } + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZAL +void rpsxBGEZAL() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + else MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLEZ +void rpsxBLEZ() +{ + // Branch if Rs <= 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] > 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JLE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JLE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +//// BGTZ +void rpsxBGTZ() +{ + // Branch if Rs > 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] <= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JG8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JG32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +void rpsxMFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxCFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxMTC0() +{ + // Cop0->Rd = Rt + if( PSX_IS_CONST1(_Rt_) ) { + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], g_psxConstRegs[_Rt_]); + } + else { + _psxDeleteReg(_Rt_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX); + } +} + +void rpsxCTC0() +{ + // Cop0->Rd = Rt + rpsxMTC0(); +} + +void rpsxRFE() +{ + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); + MOV32RtoR(ECX, EAX); + AND32ItoR(EAX, 0xfffffff0); + AND32ItoR(ECX, 0x3c); + SHR32ItoR(ECX, 2); + OR32RtoR (EAX, ECX); + MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); +} + +// R3000A tables +extern void (*rpsxBSC[64])(); +extern void (*rpsxSPC[64])(); +extern void (*rpsxREG[32])(); +extern void (*rpsxCP0[32])(); +extern void (*rpsxCP2[64])(); +extern void (*rpsxCP2BSC[32])(); + +static void rpsxSPECIAL() { rpsxSPC[_Funct_](); } +static void rpsxREGIMM() { rpsxREG[_Rt_](); } +static void rpsxCOP0() { rpsxCP0[_Rs_](); } +static void rpsxBASIC() { rpsxCP2BSC[_Rs_](); } + +static void rpsxNULL() { + SysPrintf("psxUNK: %8.8x\n", psxRegs.code); +} + +void (*rpsxBSC[64])() = { + rpsxSPECIAL, rpsxREGIMM, rpsxJ , rpsxJAL , rpsxBEQ , rpsxBNE , rpsxBLEZ, rpsxBGTZ, + rpsxADDI , rpsxADDIU , rpsxSLTI, rpsxSLTIU, rpsxANDI, rpsxORI , rpsxXORI, rpsxLUI , + rpsxCOP0 , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxLB , rpsxLH , rpsxLWL , rpsxLW , rpsxLBU , rpsxLHU , rpsxLWR , rpsxNULL, + rpsxSB , rpsxSH , rpsxSWL , rpsxSW , rpsxNULL, rpsxNULL, rpsxSWR , rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxSPC[64])() = { + rpsxSLL , rpsxNULL, rpsxSRL , rpsxSRA , rpsxSLLV , rpsxNULL , rpsxSRLV, rpsxSRAV, + rpsxJR , rpsxJALR, rpsxNULL, rpsxNULL, rpsxSYSCALL, rpsxBREAK, rpsxNULL, rpsxNULL, + rpsxMFHI, rpsxMTHI, rpsxMFLO, rpsxMTLO, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxMULT, rpsxMULTU, rpsxDIV, rpsxDIVU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxADD , rpsxADDU, rpsxSUB , rpsxSUBU, rpsxAND , rpsxOR , rpsxXOR , rpsxNOR , + rpsxNULL, rpsxNULL, rpsxSLT , rpsxSLTU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL +}; + +void (*rpsxREG[32])() = { + rpsxBLTZ , rpsxBGEZ , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxBLTZAL, rpsxBGEZAL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxCP0[32])() = { + rpsxMFC0, rpsxNULL, rpsxCFC0, rpsxNULL, rpsxMTC0, rpsxNULL, rpsxCTC0, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxRFE , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +// coissued insts +void (*rpsxBSC_co[64] )() = { + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpsxpropSetRead(reg) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpsxpropSetWrite(reg) { \ + prev->regs[reg] &= ~EEINST_LIVE0; \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +void rpsxpropBSC(EEINST* prev, EEINST* pinst); +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst); +void rpsxpropCP0(EEINST* prev, EEINST* pinst); +void rpsxpropCP2(EEINST* prev, EEINST* pinst); + +//SPECIAL, REGIMM, J , JAL , BEQ , BNE , BLEZ, BGTZ, +//ADDI , ADDIU , SLTI, SLTIU, ANDI, ORI , XORI, LUI , +//COP0 , NULL , COP2, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//LB , LH , LWL , LW , LBU , LHU , LWR , NULL, +//SB , SH , SWL , SW , NULL, NULL, SWR , NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL +void rpsxpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(psxRegs.code >> 26) { + case 0: rpsxpropSPECIAL(prev, pinst); break; + case 1: rpsxpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpsxpropSetWrite(31); + break; + case 4: // beq + case 5: // bne + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 6: // blez + case 7: // bgtz + rpsxpropSetRead(_Rs_); + break; + + case 15: // lui + rpsxpropSetWrite(_Rt_); + break; + + case 16: rpsxpropCP0(prev, pinst); break; + case 18: assert(0); break; + + // stores + case 40: case 41: case 42: case 43: case 46: + rpsxpropSetRead(_Rt_); + rpsxpropSetRead(_Rs_); + break; + + default: + rpsxpropSetWrite(_Rt_); + rpsxpropSetRead(_Rs_); + break; + } +} + +//SLL , NULL, SRL , SRA , SLLV , NULL , SRLV, SRAV, +//JR , JALR, NULL, NULL, SYSCALL, BREAK, NULL, NULL, +//MFHI, MTHI, MFLO, MTLO, NULL , NULL , NULL, NULL, +//MULT, MULTU, DIV, DIVU, NULL , NULL , NULL, NULL, +//ADD , ADDU, SUB , SUBU, AND , OR , XOR , NOR , +//NULL, NULL, SLT , SLTU, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rt_); + break; + + case 8: // JR + rpsxpropSetRead(_Rs_); + break; + case 9: // JALR + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_HI); + break; + case 17: // mthi + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + break; + case 18: // mflo + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_LO); + break; + case 19: // mtlo + rpsxpropSetWrite(PSX_LO); + rpsxpropSetRead(_Rs_); + break; + + case 24: // mult + case 25: // multu + case 26: // div + case 27: // divu + rpsxpropSetWrite(PSX_LO); + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpsxpropSetWrite(_Rd_); + if( _Rs_ ) rpsxpropSetRead(_Rs_); + if( _Rt_ ) rpsxpropSetRead(_Rt_); + break; + + default: + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + } +} + +//BLTZ , BGEZ , NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL, +//BLTZAL, BGEZAL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpsxpropSetRead(_Rs_); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpsxpropSetRead(_Rs_); + break; + + default: + assert(0); + break; + } +} + +//MFC0, NULL, CFC0, NULL, MTC0, NULL, CTC0, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//RFE , NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + case 2: // cfc0 + rpsxpropSetWrite(_Rt_); + break; + + case 4: // mtc0 + case 6: // ctc0 + rpsxpropSetRead(_Rt_); + break; + case 16: // rfe + break; + default: + assert(0); + } +} + +#endif \ No newline at end of file diff --git a/x86/iR5900.c b/x86/iR5900.c new file mode 100644 index 0000000000..2fd708a979 --- /dev/null +++ b/x86/iR5900.c @@ -0,0 +1,3118 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 +// Recompiled completely rewritten to add block level recompilation/reg-caching/ +// liveness analysis/constant propagation Apr06 (zerofrog@gmail.com) + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "VU.h" +#include "VUmicro.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +u32 maxrecmem = 0; +uptr *recLUT; + +#define X86 +#define RECSTACK_SIZE 0x00010000 + +#define EE_NUMBLOCKS (1<<14) + +static char *recMem = NULL; // the recompiled blocks will be here +static char* recStack = NULL; // stack mem +static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here +static BASEBLOCK *recROM = NULL; // and here +static BASEBLOCK *recROM1 = NULL; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr = NULL, *recStackPtr = NULL; +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_EEFreezeRegs = 0; // if set, should freeze the regs + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what pc the current block ends +static u32 s_nHasDelay = 0; + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +extern void (*recBSC[64])(); +extern void (*recBSC_co[64])(); +void rpropBSC(EEINST* prev, EEINST* pinst); + +// save states for branches +static u16 s_savex86FpuState, s_saveiCWstate; +static GPR_reg64 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_nBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +void recCOP2RecompileInst(); +int recCOP2AnalyzeBlock(u32 startpc, u32 endpc); +void recCOP2EndBlock(void); + +#ifdef _DEBUG +u32 dumplog = 0; +#else +#define dumplog 0 +#endif + +u32 pc; // recompiler pc +int branch; // set for branch +BOOL bExecBIOS = FALSE; + +#ifdef PCSX2_DEVBUILD +static LARGE_INTEGER lbase = {0}, lfinal = {0}; +static u32 s_startcount = 0; +#endif + +#ifdef __x86_64__ +char *txt0 = "RAX = %x : RDX = %x : RCX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; +#else +char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; +#endif + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls); // reccop2.c +static void iBranchTest(u32 newpc, u32 cpuBranch); +static void recRecompile( u32 startpc ); +void recCOP22( void ); + +BASEBLOCKEX* PC_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+EE_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 0); +} + +//////////////////////////////////////////////////// +void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + extern char *disRNameGPR[]; + u8 used[34]; + u8 fpuused[33]; + int numused, count, fpunumused; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, pc, cpuRegs.cycle ); +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\dump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/dump%.8X.txt", startpc); +#endif + + fflush( stdout ); +// f = fopen( "dump1", "wb" ); +// fwrite( ptr, 1, (u32)x86Ptr - (u32)ptr, f ); +// fclose( f ); +// +//#ifdef __x86_64__ +// sprintf( command, "objdump -D --target=binary --architecture=i386:x86-64 dump1 > %s", filename ); +//#else +// sprintf( command, "objdump -D --target=binary --architecture=i386 dump1 > %s", filename ); +//#endif +// system( command ); + + f = fopen( filename, "w" ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR5900Fasm( PSMu32( i ), i ) ); + } + + // write the instruction info + + fprintf(f, "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n", + EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + memset(fpuused, 0, sizeof(fpuused)); + fpunumused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( s_pInstCache->fpuregs[i] & EEINST_USED ) { + fpuused[i] = 1; + fpunumused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { + if( fpuused[j] ) { + fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count>26) { + case 26: // ldl + case 27: // ldr + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 55: // LD + case 30: // lq + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _eeIsLoadStoreCoIssue(u32 firstcode, u32 secondcode) +{ + switch(firstcode>>26) { + case 34: // lwl + return (secondcode>>26)==38; + case 38: // lwr + return (secondcode>>26)==34; + case 42: // swl + return (secondcode>>26)==46; + case 46: // swr + return (secondcode>>26)==42; + case 26: // ldl + return (secondcode>>26)==27; + case 27: // ldr + return (secondcode>>26)==26; + case 44: // sdl + return (secondcode>>26)==45; + case 45: // sdr + return (secondcode>>26)==44; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + case 30: // lq + + // stores + case 31: // sq + case 40: case 41: case 43: + case 63: // sd + case 49: // lwc1 + case 57: // swc1 + case 54: // lqc2 + case 62: // sqc2 + return (secondcode>>26)==(firstcode>>26); + } + return 0; +} + +u8 _eeIsLoadStoreCoX(u32 tempcode) +{ + switch( tempcode>>26 ) { + case 30: case 31: case 49: case 57: case 55: case 63: + return 1; + } + return 0; +} + +void _eeFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( pc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && GPR_IS_CONST1(i) ) _flushConstReg(i); + else { + _deleteMMXreg(MMX_GPR+i, 1); + _deleteGPRtoXMMreg(i, 1); + } + } + + //TODO when used info is done for FPU and VU0 + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse && xmmregs[i].type != XMMTYPE_GPRREG ) + _freeXMMreg(i); + } +} + +u32* _eeGetConstReg(int reg) +{ + assert( GPR_IS_CONST1( reg ) ); + + if( g_cpuFlushedConstReg & (1<regs[xmmregs[i].reg]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, xmmregs[i].reg) ) { + _freeXMMreg(i); + xmmregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushMMXunused() +{ + int i; + for (i=0; iregs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR) ) { + _freeMMXreg(i); + mmxregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_cpuHasConstReg & (1<regs[reg]&EEINST_LASTUSE) ) { + if( mmx ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + return _allocGPRtoXMMreg(-1, reg, mode); + } + + return -1; +} + +#define PROCESS_EE_SETMODES(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo +// core of reg caching +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo) +{ + int mmreg1, mmreg2, mmreg3, mmtemp, moded; + + if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; + + if( xmminfo&XMMINFO_WRITED) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( xmminfo & XMMINFO_WRITED ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + } + if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededMMXreg(MMX_GPR+MMX_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededMMXreg(MMX_GPR+MMX_HI); + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_MMX) { +// mmreg1 = _allocMMXreg(-1, MMX_GPR+vreg, MODE_READ); +// _addNeededMMXreg(MMX_GPR+vreg); +// } + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(vreg)) ) { + if( EEINST_ISLIVEMMX(vreg) ) { + _freeMMXreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_MMX; + + // do it all in mmx + if( mmreg1 < 0 ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + // check for last used, if so don't alloc a new MMX reg + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_)) ) { + if( EEINST_ISLIVEMMX(_Rt_) ) { + _freeMMXreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg2].inuse = 1; + mmxregs[mmreg2].reg = _Rd_; + mmxregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_)) ) { + if( EEINST_ISLIVEMMX(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI); + _addNeededGPRtoXMMreg(_Rs_); + _addNeededGPRtoXMMreg(_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) { +// mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ); +// _addNeededGPRtoXMMreg(vreg); +// } + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) { + _freeXMMreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_XMM; + + // do it all in xmm + if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg2].inuse = 1; + xmmregs[mmreg2].reg = _Rd_; + xmmregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteMMXreg(MMX_GPR+_Rd_, (xmminfo&XMMINFO_READD)?0:2); + + // don't delete, fn will take care of them +// if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { +// _deleteGPRtoXMMreg(XMMGPR_LO, (xmminfo&XMMINFO_READLO)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_LO, (xmminfo&XMMINFO_READLO)?1:0); +// } +// if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { +// _deleteGPRtoXMMreg(XMMGPR_HI, (xmminfo&XMMINFO_READHI)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_HI, (xmminfo&XMMINFO_READHI)?1:0); +// } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rt_ ) return; + + CHECK_SAVE_REG(_Rt_); + _eeProcessHasLive(_Rt_, 0); + EEINST_RESETSIGNEXT(_Rt_); + + if( GPR_IS_CONST1(_Rs_) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _deleteGPRtoXMMreg(_Rt_, 2); + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rt_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + if( EEINST_ISLIVEMMX(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rt_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rt_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rt_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rt_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rt_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rd_ ) return; + + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + + if( GPR_IS_CONST1(_Rt_) ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + if( EEINST_ISLIVEMMX(_Rt_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 2); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt op rs +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode) +{ + assert(0); + // for now, don't support xmm + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + multicode(0); +} + +// Simple Code Templates // + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 0); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rt_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rt_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 0); + + if( GPR_IS_CONST1(_Rs_) ) { + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + + if( GPR_IS_CONST1(_Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT) +{ + assert(0); + // for now, don't support xmm + if( MULT ) { + CHECK_SAVE_REG(_Rd_); + _deleteGPRtoXMMreg(_Rd_, 0); + } + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( MULT && _Rd_ ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTS); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + multicode(0); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); +} + +// EE XMM allocation code +int eeRecompileCodeXMM(int xmminfo) +{ + int info = PROCESS_EE_XMM; + + // save state + if( xmminfo & XMMINFO_WRITED ) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + // flush consts + if( xmminfo & XMMINFO_READT ) { + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + } + if( xmminfo & XMMINFO_READS) { + if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rs_); + } + } + + if( xmminfo & XMMINFO_WRITED ) { + GPR_DEL_CONST(_Rd_); + } + + // add needed + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + _addNeededGPRtoXMMreg(XMMGPR_LO); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + _addNeededGPRtoXMMreg(XMMGPR_HI); + } + if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_); + if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_); + if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_); + + // allocate + if( xmminfo & XMMINFO_READS) { + int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg); + } + if( xmminfo & XMMINFO_READT) { + int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg); + } + + if( xmminfo & XMMINFO_WRITED ) { + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0); + + int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd); + + if( regd < 0 ) { + if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(EEREC_T); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_T].inuse = 1; + xmmregs[EEREC_T].reg = _Rd_; + xmmregs[EEREC_T].mode = readd; + regd = EEREC_T; + } + else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(EEREC_S); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_S].inuse = 1; + xmmregs[EEREC_S].reg = _Rd_; + xmmregs[EEREC_S].mode = readd; + regd = EEREC_S; + } + else regd = _allocGPRtoXMMreg(-1, _Rd_, readd); + } + + info |= PROCESS_EE_SET_D(regd); + } + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0))); + info |= PROCESS_EE_LO; + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0))); + info |= PROCESS_EE_HI; + } + return info; +} + +// EE COP1(FPU) XMM allocation code +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +// rd = rs op rt +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo) +{ + int mmregs=-1, mmregt=-1, mmregd=-1, mmregacc=-1; + + if( EE_FPU_REGCACHING && cpucaps.hasStreamingSIMDExtensions ) { + int info = PROCESS_EE_XMM; + + if( xmminfo & XMMINFO_READS ) _addNeededFPtoXMMreg(_Fs_); + if( xmminfo & XMMINFO_READT ) _addNeededFPtoXMMreg(_Ft_); + if( xmminfo & (XMMINFO_WRITED|XMMINFO_READD) ) _addNeededFPtoXMMreg(_Fd_); + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) _addNeededFPACCtoXMMreg(); + + if( xmminfo & XMMINFO_READT ) { + if( g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE ) mmregt = _checkXMMreg(XMMTYPE_FPREG, _Ft_, MODE_READ); + else mmregt = _allocFPtoXMMreg(-1, _Ft_, MODE_READ); + } + + if( xmminfo & XMMINFO_READS ) { + if( (!(xmminfo&XMMINFO_READT)||mmregt>=0) && (g_pCurInstInfo->fpuregs[_Fs_] & EEINST_LASTUSE) ) + mmregs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + else mmregs = _allocFPtoXMMreg(-1, _Fs_, MODE_READ); + } + + if( mmregs >= 0 ) info |= PROCESS_EE_SETMODES(mmregs); + if( mmregt >= 0 ) info |= PROCESS_EE_SETMODET(mmregt); + + if( xmminfo & XMMINFO_READD ) { + assert( xmminfo & XMMINFO_WRITED ); + mmregd = _allocFPtoXMMreg(-1, _Fd_, MODE_READ); + } + + if( xmminfo & XMMINFO_READACC ) { + if( !(xmminfo&XMMINFO_WRITEACC) && (g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE) ) + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, MODE_READ); + else mmregacc = _allocFPACCtoXMMreg(-1, MODE_READ); + } + + if( xmminfo & XMMINFO_WRITEACC ) { + + // check for last used, if so don't alloc a new XMM reg + int readacc = MODE_WRITE|((xmminfo&XMMINFO_READACC)?MODE_READ:0); + + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, readacc); + + if( mmregacc < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) _freeXMMreg(mmregt); + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = 0; + xmmregs[mmregt].mode = readacc; + xmmregs[mmregt].type = XMMTYPE_FPACC; + mmregacc = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) _freeXMMreg(mmregs); + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = 0; + xmmregs[mmregs].mode = readacc; + xmmregs[mmregs].type = XMMTYPE_FPACC; + mmregacc = mmregs; + } + else mmregacc = _allocFPACCtoXMMreg(-1, readacc); + } + + xmmregs[mmregacc].mode |= MODE_WRITE; + } + else if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + if( xmminfo&XMMINFO_READD ) mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + else mmregd = _checkXMMreg(XMMTYPE_FPREG, _Fd_, readd); + + if( mmregd < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) _freeXMMreg(mmregt); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = _Fd_; + xmmregs[mmregt].mode = readd; + mmregd = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) _freeXMMreg(mmregs); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = _Fd_; + xmmregs[mmregs].mode = readd; + mmregd = mmregs; + } + else if( (xmminfo&XMMINFO_READACC) && mmregacc >= 0 && (FPUINST_LASTUSE(XMMFPU_ACC) || !FPUINST_ISLIVE(XMMFPU_ACC)) ) { + if( FPUINST_ISLIVE(XMMFPU_ACC) ) _freeXMMreg(mmregacc); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregacc].inuse = 1; + xmmregs[mmregacc].reg = _Fd_; + xmmregs[mmregacc].mode = readd; + xmmregs[mmregacc].type = XMMTYPE_FPREG; + mmregd = mmregacc; + } + else mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + } + } + + assert( mmregs >= 0 || mmregt >= 0 || mmregd >= 0 || mmregacc >= 0 ); + + if( xmminfo & XMMINFO_WRITED ) { + assert( mmregd >= 0 ); + info |= PROCESS_EE_SET_D(mmregd); + } + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) { + if( mmregacc >= 0 ) info |= PROCESS_EE_SET_ACC(mmregacc)|PROCESS_EE_ACC; + else assert( !(xmminfo&XMMINFO_WRITEACC)); + } + + if( xmminfo & XMMINFO_READS ) { + if( mmregs >= 0 ) info |= PROCESS_EE_SET_S(mmregs)|PROCESS_EE_S; + } + if( xmminfo & XMMINFO_READT ) { + if( mmregt >= 0 ) info |= PROCESS_EE_SET_T(mmregt)|PROCESS_EE_T; + } + + // at least one must be in xmm + if( (xmminfo & (XMMINFO_READS|XMMINFO_READT)) == (XMMINFO_READS|XMMINFO_READT) ) { + assert( mmregs >= 0 || mmregt >= 0 ); + } + + xmmcode(info); + _clearNeededXMMregs(); + return; + } + + if( xmminfo & XMMINFO_READS ) _deleteFPtoXMMreg(_Fs_, 0); + if( xmminfo & XMMINFO_READT ) _deleteFPtoXMMreg(_Ft_, 0); + if( xmminfo & (XMMINFO_READD|XMMINFO_WRITED) ) _deleteFPtoXMMreg(_Fd_, 0); + if( xmminfo & (XMMINFO_READACC|XMMINFO_WRITEACC) ) _deleteFPtoXMMreg(XMMFPU_ACC, 0); + fpucode(0); +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +//////////////////////////////////////////////////// +extern u8 g_MACFlagTransform[256]; // for vus + +u32 g_sseMXCSR = 0x9f80; // disable all exception, round to 0, flush to 0 +u32 g_sseVUMXCSR = 0xff80; +void SetCPUState() +{ + // SSE STATE // + // do NOT set Denormals-Are-Zero flag (charlie and chocfac messes up) + g_sseMXCSR = 0x9f80; // changing the rounding mode to 0x2000 (near) kills grandia III! + // changing the rounding mode to 0x0000 or 0x4000 totally kills gitaroo + // so... grandia III wins + + __asm ldmxcsr g_sseMXCSR // set the new sse control + g_sseVUMXCSR = g_sseMXCSR|0x6000; +} + +extern BOOL install_my_handler(); + +int recInit( void ) +{ + int i; + const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + + recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 ); + memset( recLUT, 0, 0x010000 * sizeof(uptr) ); + recMem = (char*)SysMmap(0, 0x00c00000); + + // 32 alignment necessary + recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK)); + recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK)); + recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK)); + recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16); + recStack = (char*)malloc( RECSTACK_SIZE ); + + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize ); + + if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) { + SysMessage( _( "Error allocating memory" ) ); + return -1; + } + + for ( i = 0x0000; i < 0x0200; i++ ) + { + recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x2000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x3000 ] = (uptr)&recRAM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0040; i++ ) + { + recLUT[ i + 0x1fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0x9fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0xbfc0 ] = (uptr)&recROM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0004; i++ ) + { + recLUT[ i + 0x1e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0x9e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0xbe00 ] = (uptr)&recROM1[ i << 14 ]; + } + + memcpy( recLUT + 0x8000, recLUT, 0x2000 * sizeof(uptr) ); + memcpy( recLUT + 0xa000, recLUT, 0x2000 * sizeof(uptr) ); + + memset(recMem, 0xcd, 0x00c00000); + memset(recStack, 0, RECSTACK_SIZE); + + // SSE3 detection, manually create the code + x86SetPtr(recMem); + SSE3_MOVSLDUP_XMM_to_XMM(XMM0, XMM0); + RET(); + + cpucaps.hasStreamingSIMD3Extensions = 1; + __try { + __asm call recMem + } + __except(EXCEPTION_EXECUTE_HANDLER) { + cpucaps.hasStreamingSIMD3Extensions = 0; + +#ifdef WIN32_VIRTUAL_MEM + // necessary since can potentially kill the custom handler + install_my_handler(); +#endif + } + + SysPrintf( "x86Init: \n" ); + SysPrintf( "\tCPU vender name = %s\n", cpuinfo.x86ID ); + SysPrintf( "\tFamilyID = %x\n", cpuinfo.x86StepID ); + SysPrintf( "\tx86Family = %s\n", cpuinfo.x86Fam ); + SysPrintf( "\tCPU speed = %d MHZ\n", cpuinfo.cpuspeed); + SysPrintf( "\tx86PType = %s\n", cpuinfo.x86Type ); + SysPrintf( "\tx86Flags = %8.8x\n", cpuinfo.x86Flags ); + SysPrintf( "\tx86EFlags = %8.8x\n", cpuinfo.x86EFlags ); + SysPrintf( "Features: \n" ); + SysPrintf( "\t%sDetected MMX\n", cpucaps.hasMultimediaExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE\n", cpucaps.hasStreamingSIMDExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE2\n", cpucaps.hasStreamingSIMD2Extensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE3\n", cpucaps.hasStreamingSIMD3Extensions ? "" : "Not " ); + + if ( cpuinfo.x86ID[0] == 'A' ) //AMD cpu + { + SysPrintf( " Extented AMD Features: \n" ); + SysPrintf( "\t%sDetected MMX2\n", cpucaps.hasMultimediaExtensionsExt ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW\n", cpucaps.has3DNOWInstructionExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW2\n", cpucaps.has3DNOWInstructionExtensionsExt ? "" : "Not " ); + } + if ( !( cpucaps.hasMultimediaExtensions ) ) + { + SysMessage( _( "Processor doesn't supports MMX, can't run recompiler without that" ) ); + return -1; + } + + x86FpuState = FPU_STATE; + + SuperVUInit(-1); + + for(i = 0; i < 256; ++i) { + g_MACFlagTransform[i] = macarr[i>>4]|(macarr[i&15]<<4); + } + + SetCPUState(); + + return 0; +} + +//////////////////////////////////////////////////// +void recReset( void ) { +#ifdef PCSX2_DEVBUILD + SysPrintf("EE Recompiler data reset\n"); +#endif + + s_nNextBlock = 0; + maxrecmem = 0; + memset( recRAM, 0, sizeof(BASEBLOCK)/4*0x02000000 ); + memset( recROM, 0, sizeof(BASEBLOCK)/4*0x00400000 ); + memset( recROM1, 0, sizeof(BASEBLOCK)/4*0x00040000 ); + memset( recBlocks, 0, sizeof(BASEBLOCKEX)*EE_NUMBLOCKS ); + if( s_pInstCache ) memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); + ResetBaseBlockEx(0); + + __asm emms + +#ifdef _DEBUG + // don't clear since save states won't work + //memset(recMem, 0xcd, 0x00c00000); +#endif + + recPtr = recMem; + recStackPtr = recStack; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +void recShutdown( void ) +{ + if ( recMem == NULL ) { + return; + } + + _aligned_free( recLUT ); + SysMunmap((uptr)recMem, 0x00800000); recMem = NULL; + _aligned_free( recRAM ); recRAM = NULL; + _aligned_free( recROM ); recROM = NULL; + _aligned_free( recROM1 ); recROM1 = NULL; + _aligned_free( recBlocks ); recBlocks = NULL; + free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0; + + SuperVUDestroy(-1); + + x86Shutdown( ); +} + +void recEnableVU0micro(int enable) { +} + +void recEnableVU1micro(int enable) { +} + +#pragma warning(disable:4731) // frame pointer register 'ebp' modified by inline assembly code +static u32 s_uSaveESP = 0, s_uSaveEBP; + +static void execute( void ) +{ +#ifdef _DEBUG + u8* fnptr; + u32 oldesi; +#else + R5900FNPTR pfn; +#endif + BASEBLOCK* pblock = PC_GETBLOCK(cpuRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != cpuRegs.pc ) { + recRecompile(cpuRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + g_EEFreezeRegs = 1; + + // skip the POPs +#ifdef _DEBUG + fnptr = (u8*)pblock->pFnptr; + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + mov s_uSaveEBP, ebp + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + pfn = ((R5900FNPTR)pblock->pFnptr); + // use call instead of pfn() + //__asm mov s_uSaveEBP, ebp + __asm call pfn + +#endif + + g_EEFreezeRegs = 0; +} + +void recStep( void ) { +} + +void recExecute( void ) { + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);//ABOVE_NORMAL_PRIORITY_CLASS); + if( Config.Options & PCSX2_EEREC ) Config.Options |= PCSX2_COP2REC; + + for (;;) + execute(); +} + +void recExecuteBlock( void ) { + execute(); +} + +//////////////////////////////////////////////////// +extern u32 g_nextBranchCycle; + +u32 g_lastpc = 0; +static u32 g_temp; + +// jumped to when invalid pc address +__declspec(naked,noreturn) void Dispatcher() +{ + // EDX contains the current pc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == cpuRegs.pc + mov ecx, cpuRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push cpuRegs.pc // pc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new pc +// and eax, 0x0fffffff +// mov ecx, cpuRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void DispatcherClear() +{ + // EDX contains the current pc + __asm mov cpuRegs.pc, edx + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + if( s_pDispatchBlock->startpc == cpuRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable pc address +__declspec(naked,noreturn) void DispatcherReg() +{ + __asm { + //s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + mov edx, cpuRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == cpuRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +//////////////////////////////////////////////////// +void recClear64(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 16)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); +} + +void recClear128(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 32)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); + if( left > 2 && *(u32*)(p+2) ) recClearMem(p+2); + if( left > 3 && *(u32*)(p+3) ) recClearMem(p+3); +} + +void recClear( u32 Addr, u32 Size ) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + REC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void recClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms + if (cpucaps.has3DNOWInstructionExtensions) __asm femms + else __asm emms + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + recClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PC_GETBLOCK(p->startpc); + pexblock = PC_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 0); + pexblock->size = 0; + pexblock->startpc = 0; +} + +// check for end of bios +void CheckForBIOSEnd() +{ + MOV32MtoR(EAX, (int)&cpuRegs.pc); + + CMP32ItoR(EAX, 0x00200008); + j8Ptr[0] = JE8(0); + + CMP32ItoR(EAX, 0x00100008); + j8Ptr[1] = JE8(0); + + // return + j8Ptr[2] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[1] ); + + // bios end + RET2(); + + x86SetJ8( j8Ptr[2] ); +} + +static int *s_pCode; + +void SetBranchReg( u32 reg ) +{ + branch = 1; + + if( reg != 0xffffffff ) { +// if( GPR_IS_CONST1(reg) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[reg].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+reg, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ reg ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, reg); + + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + } + +// CMP32ItoM((u32)&cpuRegs.pc, 0); +// j8Ptr[5] = JNE8(0); +// CALLFunc((u32)tempfn); +// x86SetJ8( j8Ptr[5] ); + + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void SetBranchImm( u32 imm ) +{ + u32* ptr; + branch = 1; + + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&cpuRegs.pc, imm ); + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(imm, imm <= pc); + if( bExecBIOS ) CheckForBIOSEnd(); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)Dispatcher - ( (u32)x86Ptr + 5 )); +} + +void SaveBranchState() +{ + s_savex86FpuState = x86FpuState; + s_saveiCWstate = iCWstate; + s_savenBlockCycles = s_nBlockCycles; + s_saveConstGPRreg = 0xffffffff; // indicate searching + s_saveHasConstReg = g_cpuHasConstReg; + s_saveFlushedConstReg = g_cpuFlushedConstReg; + s_psaveInstInfo = g_pCurInstInfo; + s_saveRegHasLive1 = g_cpuRegHasLive1; + s_saveRegHasSignExt = g_cpuRegHasSignExt; + + // save all mmx regs + memcpy(s_saveMMXregs, mmxregs, sizeof(mmxregs)); + memcpy(s_saveXMMregs, xmmregs, sizeof(xmmregs)); +} + +void LoadBranchState() +{ + x86FpuState = s_savex86FpuState; + iCWstate = s_saveiCWstate; + s_nBlockCycles = s_savenBlockCycles; + + if( s_saveConstGPRreg != 0xffffffff ) { + assert( s_saveConstGPRreg > 0 ); + + // make sure right GPR was saved + assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<ltime); + CALLFunc((u32)_StopPerfCounter); + } +#endif +} + +#define USE_FAST_BRANCHES 0 + +//void testfpu() +//{ +// int i; +// for(i = 0; i < 32; ++i ) { +// if( fpuRegs.fpr[i].UL== 0x7f800000 || fpuRegs.fpr[i].UL == 0xffc00000) { +// SysPrintf("bad fpu: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// +// if( VU0.VF[i].UL[0] == 0xffc00000 || //(VU0.VF[i].UL[1]&0xffc00000) == 0xffc00000 || +// VU0.VF[i].UL[0] == 0x7f800000) { +// SysPrintf("bad vu0: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// } +//} + +//static void cleanup() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +static void iBranchTest(u32 newpc, u32 cpuBranch) +{ +#ifdef PCSX2_DEVBUILD + if( s_startcount ) { + StopPerfCounter(); + ADD32ItoM( (u32)&s_pCurBlockEx->visited, 1 ); + } +#endif + +#ifdef _DEBUG + //CALLFunc((u32)testfpu); +#endif + + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&cpuRegs.cycle); + ADD32ItoR(ECX, s_nBlockCycles*9/8); // NOTE: mulitply cycles here, 6/5 ratio stops pal ffx from randomly crashing, but crashes jakI + MOV32RtoM((int)&cpuRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + return; + } + + SUB32MtoR(ECX, (int)&g_nextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + // has to be in the middle of Save/LoadBranchState + CALLFunc( (int)cpuBranchTest ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&cpuRegs.pc, newpc); + JNE32((u32)DispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + + +//////////////////////////////////////////////////// +#ifndef CP2_RECOMPILE + +REC_SYS(COP2); + +#else + +void recCOP2( void ) +{ +#ifdef CPU_LOG + CPU_LOG( "Recompiling COP2:%s\n", disR5900Fasm( cpuRegs.code, cpuRegs.pc ) ); +#endif + +// if ( !CHECK_COP2REC ) //disable the use of vus better this way :P +// { +// assert( !CHECK_EEREC ); +// MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (u32)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// g_cpuHasConstReg = 1; // reset all since COP2 can change regs +// CALLFunc( (u32)COP2 ); +// +// CMP32ItoM((int)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); +// JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); +// x86SetJ8(j8Ptr[0]); +//// branch = 2; +// } +// else + { + recCOP22( ); + } +} + +#endif + +//////////////////////////////////////////////////// +void recSYSCALL( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)SYSCALL ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +void recBREAK( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BREAK ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + RET(); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +static void checkcodefn() +{ + int pctemp; + + __asm mov pctemp, eax + SysPrintf("code changed! %x\n", pctemp); + assert(0); +} + +void checkpchanged(u32 startpc) +{ + assert(0); +} + +//#ifdef _DEBUG +//#define CHECK_XMMCHANGED() CALLFunc((u32)checkxmmchanged); +//#else +//#define CHECK_XMMCHANGED() +//#endif +// +//static void checkxmmchanged() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +u32 recompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PC_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pc == pblock->startpc ) + return 0; + } + + return 1; +} + +void recompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + int i, count; + + BASEBLOCK* pblock = PC_GETBLOCK(pc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && pc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PC_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == pc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + recClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", pc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSM( pc ); + assert(s_pCode); + +#ifdef _DEBUG + MOV32ItoR(EAX, pc); +#endif + + cpuRegs.code = *(int *)s_pCode; + s_nBlockCycles++; + pc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, cpuRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, pc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +// +// if( !delayslot ) { +// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); +// j8Ptr[0] = JB8(0); +// CMP32ItoM((u32)&cpuRegs.pc, pc); +// j8Ptr[1] = JA8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[ 0 ] ); +// x86SetJ8( j8Ptr[ 1 ] ); +// PUSH32I(s_pCurBlockEx->startpc); +// CALLFunc((u32)checkpchanged); +// ADD32ItoR(ESP, 4); +// x86SetJ8( j8Ptr[ 2 ] ); +// } +//#endif + + g_pCurInstInfo++; + + // reorder register priorities +// for(i = 0; i < X86REGS; ++i) { +// if( x86regs[i].inuse ) { +// if( count > 0 ) mmxregs[i].counter = 1000-count; +// else mmxregs[i].counter = 0; +// } +// } + + for(i = 0; i < MMXREGS; ++i) { + if( mmxregs[i].inuse ) { + assert( MMX_ISGPR(mmxregs[i].reg) ); + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR); + if( count > 0 ) mmxregs[i].counter = 1000-count; + else mmxregs[i].counter = 0; + } + } + + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse ) { + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, xmmregs[i].type, xmmregs[i].reg); + if( count > 0 ) xmmregs[i].counter = 1000-count; + else xmmregs[i].counter = 0; + } + } + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + +#ifdef WIN32_VIRTUAL_MEM + if( g_pCurInstInfo->numpeeps > 1 ) { + switch(cpuRegs.code>>26) { + case 30: recLQ_coX(g_pCurInstInfo->numpeeps); break; + case 31: recSQ_coX(g_pCurInstInfo->numpeeps); break; + case 49: recLWC1_coX(g_pCurInstInfo->numpeeps); break; + case 57: recSWC1_coX(g_pCurInstInfo->numpeeps); break; + case 55: recLD_coX(g_pCurInstInfo->numpeeps); break; + case 63: recSD_coX(g_pCurInstInfo->numpeeps); break; + default: + assert(0); + } + + pc += g_pCurInstInfo->numpeeps*4; + s_nBlockCycles += g_pCurInstInfo->numpeeps; + g_pCurInstInfo += g_pCurInstInfo->numpeeps; + } + else { + recBSC_co[cpuRegs.code>>26](); + pc += 4; + s_nBlockCycles++; + g_pCurInstInfo++; + } +#else + assert(0); +#endif + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + + recBSC[ cpuRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //if( !_flushUnusedConstReg() ) { + int flushed = 0; + if( _getNumMMXwrite() > 3 ) flushed = _flushMMXunused(); + if( !flushed && _getNumXMMwrite() > 2 ) _flushXMMunused(); + s_bFlushReg = !flushed; +// } +// else s_bFlushReg = 0; + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + //CHECK_XMMCHANGED(); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +__declspec(naked) void iDummyBlock() +{ +// g_lastpc = cpuRegs.pc; +// +// do { +// cpuRegs.cycle = g_nextBranchCycle; +// cpuBranchTest(); +// } while(g_lastpc == cpuRegs.pc); +// +// __asm jmp DispatcherReg + __asm { +RepDummy: + add cpuRegs.cycle, 9 + call cpuBranchTest + cmp cpuRegs.pc, 0x81fc0 + je RepDummy + jmp DispatcherReg + } +} + +//////////////////////////////////////////////////// +#include "r3000a.h" +#include "PsxCounters.h" +extern tIPU_BP g_BP; + +extern u32 psxdump; +extern u32 psxNextCounter, psxNextsCounter; +extern void iDumpPsxRegisters(u32 startpc, u32 temp); +extern Counter counters[6]; +void iDumpRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 }; + + __Log("%sreg: %x %x\n", pstr, startpc, cpuRegs.interrupt); + for(i = 1; i < 32; ++i) __Log("%s%d: %x_%x_%x_%x\n", pstr, i, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]); + //for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x\n", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]); + //for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x\n", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL); + for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x\n", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]); + for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x\n", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + __Log("%svfACC: %x %x %x %x\n", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]); + __Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x\n", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], + cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]); + __Log("%sCycle: %x %x, Count: %x\n", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count); + iDumpPsxRegisters(psxRegs.pc, temp); + + __Log("cyc11: %x %x; vu0: %x, vu1: %x\n", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle); + + __Log("%scounters: %x %x; psx: %x %x\n", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter); + for(i = 0; i < 4; ++i) { + __Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x\n", i, + counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate, + counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT); + } + __Log("ipu %x %x %x %x; bp: %x %x %x %x\n", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC); + __Log("gif: %x %x %x\n", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); + for(i = 0; i < ARRAYSIZE(dmacs); ++i) { + DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]); + __Log("dma%d c%x m%x q%x t%x s%x\n", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr); + } + __Log("dmac %x %x %x %x\n", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); + __Log("intc %x %x\n", psHu32(INTC_STAT), psHu32(INTC_MASK)); + __Log("sif: %x %x %x %x %x\n", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); +} + +extern u32 psxdump; + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0, count2 = 0; + const int skip = 0; + static int i; + + assert( !g_globalMMXSaved ); + assert( !g_globalXMMSaved ); + +#ifdef _DEBUG + __asm stmxcsr i + assert( i = g_sseMXCSR ); +#endif + + if( (dumplog&2) ) {//&& lastrec != g_lastpc ) { + + curcount++; + + if( curcount > skip ) { + iDumpRegisters(g_lastpc, 1); + curcount = 0; + } + + lastrec = g_lastpc; + } +} + +u32 s_recblocks[] = {0}; + +void badespfn() { + assert(0); + SysPrintf("Bad esp!\n"); +} + +#define OPTIMIZE_COP2 0//CHECK_VU0REC + +static void recRecompile( u32 startpc ) +{ + u32 i = 0; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + u32 usecop2; + +#ifdef _DEBUG + //dumplog |= 4; + if( dumplog & 4 ) + iDumpRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if ( ( (uptr)recPtr - (uptr)recMem ) >= 0xb92000 || dumplog == 0xffffffff) { + recReset(); + } + if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) { +#ifdef _DEBUG + SysPrintf("stack reset\n"); +#endif + recReset(); + } + + s_pCurBlock = PC_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + recClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < EE_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%EE_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%EE_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%EE_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_pCurBlock->startpc = startpc; + + // slower +// if( startpc == 0x81fc0 ) { +// +// MOV32MtoR(ECX, (u32)&g_nextBranchCycle); +// MOV32RtoM((u32)&cpuRegs.cycle, ECX); +// //ADD32ItoR(ECX, 9); +// //ADD32ItoM((u32)&cpuRegs.cycle, 512); +// CALLFunc((u32)cpuBranchTest); +// CMP32ItoM((u32)&cpuRegs.pc, 0x81fc0); +// JE8(s_pCurBlock->pFnptr - (u32)(x86Ptr+2) ); +// JMP32((u32)DispatcherReg - (u32)(x86Ptr+5)); +// +// pc = startpc + 9*4; +// assert( (pc-startpc)>>2 <= 0xffff ); +// s_pCurBlockEx->size = (pc-startpc)>>2; +// +// for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // don't overwrite if delay slot +// if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // set the block ptr +// AddBaseBlockEx(s_pCurBlockEx, 0); +// +// if( !(pc&0x10000000) ) +// maxrecmem = max( (pc&~0xa0000000), maxrecmem ); +// +// recPtr = x86Ptr; +// return; +// } + + branch = 0; + + // reset recomp state variables + s_nBlockCycles = 0; + pc = startpc; + x86FpuState = FPU_STATE; + iCWstate = 0; + s_saveConstGPRreg = 0; + g_cpuHasConstReg = g_cpuFlushedConstReg = 1; + g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; + g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; + _recClearWritebacks(); + assert( g_cpuConstRegs[0].UD[0] == 0 ); + + _initX86regs(); + _initXMMregs(); + _initMMXregs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_lastpc, pc); + CALLFunc((u32)printfn); + +// CMP32MtoR(EBP, (u32)&s_uSaveEBP); +// j8Ptr[0] = JE8(0); +// CALLFunc((u32)badespfn); +// x86SetJ8(j8Ptr[0]); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + s_nHasDelay = 0; + + while(1) { + BASEBLOCK* pblock = PC_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + cpuRegs.code = *(int *)PSM(i); + + switch(cpuRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + s_nHasDelay = 1; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ < 4 || (_Rt_ >= 16 && _Rt_ < 20) ) { + // branches + if( _Rt_ == 2 && _Rt_ == 3 && _Rt_ == 18 && _Rt_ == 19 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nHasDelay = 1; + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + case 20: case 21: case 22: case 23: + + if( (cpuRegs.code >> 26) >= 20 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + + case 16: // cp0 + if( _Rs_ == 16 ) { + if( _Funct_ == 24 ) { // eret + s_nEndBlock = i+4; + goto StartRecomp; + } + } + + break; + case 17: // cp1 + case 18: // cp2 + if( _Rs_ == 8 ) { + // BC1F, BC1T, BC1FL, BC1TL + // BC2F, BC2T, BC2FL, BC2TL + if( _Rt_ >= 2 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + break; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + cpuRegs.code = *(int *)PSM(i-4); + pcur[-1] = pcur[0]; + rpropBSC(pcur-1, pcur); + pcur--; + } + } + + // analyze instructions // + { + usecop2 = 0; + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock; i += 4) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(i); + + // cop2 // + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + + if( !usecop2 ) { + // init + if( OPTIMIZE_COP2 ) { + memset(VU0.fmac,0,sizeof(VU0.fmac)); + memset(&VU0.fdiv,0,sizeof(VU0.fdiv)); + memset(&VU0.efu,0,sizeof(VU0.efu)); + } + vucycle = 0; + usecop2 = 1; + } + + VU0.code = cpuRegs.code; + _cop2AnalyzeOp(g_pCurInstInfo, OPTIMIZE_COP2); + continue; + } + + if( usecop2 ) vucycle++; + + // peephole optimizations // +#ifdef WIN32_VIRTUAL_MEM + if( i < s_nEndBlock-4 && recompileCodeSafe(i) ) { + u32 curcode = cpuRegs.code; + u32 nextcode = *(u32*)PSM(i+4); + if( _eeIsLoadStoreCoIssue(curcode, nextcode) && recBSC_co[curcode>>26] != NULL ) { + + // rs has to be the same, and cannot be just written + if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_eeLoadWritesRs(curcode) ) { + + if( _eeIsLoadStoreCoX(curcode) && ((nextcode>>16)&0x1f) != ((curcode>>21)&0x1f) ) { + // see how many stores there are + u32 j; + // use xmmregs since only supporting lwc1,lq,swc1,sq + for(j = i+8; j < s_nEndBlock && j < i+4*XMMREGS; j += 4 ) { + u32 nncode = *(u32*)PSM(j); + if( (nncode>>26) != (curcode>>26) || ((curcode>>21)&0x1f) != ((nncode>>21)&0x1f) || + _eeLoadWritesRs(nncode)) + break; + } + + if( j > i+8 ) { + u32 num = (j-i)>>2; // number of stores that can coissue + assert( num <= XMMREGS ); + + g_pCurInstInfo[0].numpeeps = num-1; + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + + while(i < j-4) { + g_pCurInstInfo++; + g_pCurInstInfo[0].info |= EEINSTINFO_NOREC; + i += 4; + } + + continue; + } + + // fall through + } + + // unaligned loadstores + + // if LWL, check if LWR and that offsets are +3 away + switch(curcode >> 26) { + case 0x22: // LWL + if( (nextcode>>26) != 0x26 || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x26: // LWR + if( (nextcode>>26) != 0x22 || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x2a: // SWL + if( (nextcode>>26) != 0x2e || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x2e: // SWR + if( (nextcode>>26) != 0x2a || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x1a: // LDL + if( (nextcode>>26) != 0x1b || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x1b: // LWR + if( (nextcode>>26) != 0x1aa || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + + case 0x2c: // SWL + if( (nextcode>>26) != 0x2d || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x2d: // SWR + if( (nextcode>>26) != 0x2c || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + } + + // good enough + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + g_pCurInstInfo[0].numpeeps = 1; + g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; + g_pCurInstInfo++; + i += 4; + continue; + } + } + } +#endif // end peephole + } + + if( usecop2 ) { + // add necessary mac writebacks + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock-4; i += 4) { + g_pCurInstInfo++; + + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + } + } + } + } + + // perf counters // +#ifdef PCSX2_DEVBUILD + s_startcount = 0; +// if( pc+32 < s_nEndBlock ) { +// // only blocks with more than 8 insts +// PUSH32I((u32)&lbase); +// CALLFunc((u32)QueryPerformanceCounter); +// s_startcount = 1; +// } +#endif + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + // finally recompile // + g_pCurInstInfo = s_pInstCache; + while (!branch && pc < s_nEndBlock) { + recompileNextInstruction(0); + } + +#ifdef _DEBUG + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + assert( (pc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (pc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 0); +// if( p[1].startpc == p[0].startpc + 4 ) { +// assert( p[1].pFnptr != 0 ); +// // already fn in place, so add to list +// AddBaseBlockEx(s_pCurBlockEx, 0); +// } +// else +// *(BASEBLOCKEX**)(p+1) = pex; +// } + + //PC_SETBLOCKEX(s_pCurBlock, s_pCurBlockEx); + + if( !(pc&0x10000000) ) + maxrecmem = max( (pc&~0xa0000000), maxrecmem ); + + if( branch == 2 ) { + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( branch != 3 ); + if( branch ) assert( !willbranch3 ); + else ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + + if( willbranch3 ) { + BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock); + assert( pc == s_nEndBlock ); + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + } + else if( !branch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + + iFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+0x00c00000 ); + assert( recStackPtr < recStack+RECSTACK_SIZE ); + assert( x86FpuState == 0 ); + + recPtr = x86Ptr; + + assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); + + if( !branch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PC_GETBLOCK(pc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != pc ) + recRecompile(pc); + + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R5900cpu recCpu = { + recInit, + recReset, + recStep, + recExecute, + recExecuteBlock, + recExecuteVU0Block, + recExecuteVU1Block, + recEnableVU0micro, + recEnableVU1micro, + recClear, + recClearVU0, + recClearVU1, + recShutdown +}; diff --git a/x86/iR5900.h b/x86/iR5900.h new file mode 100644 index 0000000000..848f1c9cbf --- /dev/null +++ b/x86/iR5900.h @@ -0,0 +1,256 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900_H__ +#define __IR5900_H__ + +#include "VU.h" +#include "iCore.h" + +// these might not work anymore +#define ARITHMETICIMM_RECOMPILE +#define ARITHMETIC_RECOMPILE +#define MULTDIV_RECOMPILE +#define SHIFT_RECOMPILE +#define BRANCH_RECOMPILE +#define JUMP_RECOMPILE +#define LOADSTORE_RECOMPILE +#define MOVE_RECOMPILE +#define MMI_RECOMPILE +#define MMI0_RECOMPILE +#define MMI1_RECOMPILE +#define MMI2_RECOMPILE +#define MMI3_RECOMPILE +#define FPU_RECOMPILE +#define CP0_RECOMPILE +#define CP2_RECOMPILE + +#define EE_CONST_PROP // rec2 - enables constant propagation (faster) +#define EE_FPU_REGCACHING 1 + +#define PC_GETBLOCK(x) PC_GETBLOCK_(x, recLUT) + +void recClearMem(BASEBLOCK* p); +#define REC_CLEARM(mem) { \ + if ((mem) < maxrecmem && recLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PC_GETBLOCK(mem); \ + if( *(u32*)p ) recClearMem(p); \ + } \ +} \ + +extern u32 pc; +extern int branch; +extern uptr* recLUT; + +extern u32 pc; // recompiler pc +extern int branch; // set for branch +extern u32 target; // branch target +extern u16 x86FpuState; +extern u16 iCWstate; +extern u32 s_nBlockCycles; // cycles of current block recompiling + +#define REC_FUNC_INLINE( f, delreg ) \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); + +#define REC_FUNC( f, delreg ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); \ + } + +#define REC_SYS( f ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc( (u32)f ); \ + branch = 2; \ + } + +// used when processing branches +void SaveBranchState(); +void LoadBranchState(); + +void recompileNextInstruction(int delayslot); +void SetBranchReg( u32 reg ); +void SetBranchImm( u32 imm ); + +void iFlushCall(int flushtype); +void SaveCW(); +void LoadCW(); + +extern void (*recBSC[64])(); +extern void (*recSPC[64])(); +extern void (*recREG[32])(); +extern void (*recCP0[32])(); +extern void (*recCP0BC0[32])(); +extern void (*recCP0C0[64])(); +extern void (*recCP1[32])(); +extern void (*recCP1BC1[32])(); +extern void (*recCP1S[64])(); +extern void (*recCP1W[64])(); +extern void (*recMMIt[64])(); +extern void (*recMMI0t[32])(); +extern void (*recMMI1t[32])(); +extern void (*recMMI2t[32])(); +extern void (*recMMI3t[32])(); + +u32* _eeGetConstReg(int reg); // gets a memory pointer to the constant reg + +void _eeFlushAllUnused(); +void _eeOnWriteReg(int reg, int signext); + +// totally deletes from const, xmm, and mmx entries +// if flush is 1, also flushes to memory +// if 0, only flushes if not an xmm reg (used when overwriting lower 64bits of reg) +void _deleteEEreg(int reg, int flush); + +// allocates memory on the instruction size and returns the pointer +void* recAllocStackMem(int size, int align); + +////////////////////////////////////// +// Templates for code recompilation // +////////////////////////////////////// +typedef void (*R5900FNPTR)(); +typedef void (*R5900FNPTR_INFO)(int info); + +#define EERECOMPILE_CODE0(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeRecompileCode0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_, xmminfo); \ +} \ + +#define EERECOMPILE_CODEX(codename, fn) \ +void rec##fn(void) \ +{ \ + codename(rec##fn##_const, rec##fn##_); \ +} \ + +// +// MMX/XMM caching helpers +// + +// rd = rs op rt +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo); +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rt op rs (SPECIAL) +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define EERECOMPILE_CONSTCODE0(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_); \ +} \ + +// rt = rs op imm16 +#define EERECOMPILE_CONSTCODE1(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst1(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op sa +#define EERECOMPILE_CONSTCODE2(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst2(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op rs +#define EERECOMPILE_CONSTCODESPECIAL(fn, mult) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConstSPECIAL(rec##fn##_const, rec##fn##_, mult); \ +} \ + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode); +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT); + +// XMM caching helpers +#define XMMINFO_READLO 0x01 +#define XMMINFO_READHI 0x02 +#define XMMINFO_WRITELO 0x04 +#define XMMINFO_WRITEHI 0x08 +#define XMMINFO_WRITED 0x10 +#define XMMINFO_READD 0x20 +#define XMMINFO_READS 0x40 +#define XMMINFO_READT 0x80 +#define XMMINFO_READD_LO 0x100 // if set and XMMINFO_READD is set, reads only low 64 bits of D +#define XMMINFO_READACC 0x200 +#define XMMINFO_WRITEACC 0x400 + +#define CPU_SSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_SSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_FPUSSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeFPURecompileCodeXMM(xmminfo); \ + +#define CPU_FPUSSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeFPURecompileCodeXMM(xmminfo); \ + +#define CPU_SSE_XMMCACHE_END \ + _clearNeededXMMregs(); \ + return; \ + } \ + +#define FPURECOMPILE_CONSTCODE(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeFPURecompileCode(rec##fn##_xmm, rec##fn##_, xmminfo); \ +} \ + +// rd = rs op rt (all regs need to be in xmm) +int eeRecompileCodeXMM(int xmminfo); +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo); + +#endif // __IR5900_H__ \ No newline at end of file diff --git a/x86/iVU0micro.c b/x86/iVU0micro.c new file mode 100644 index 0000000000..e72325204f --- /dev/null +++ b/x86/iVU0micro.c @@ -0,0 +1,789 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +static VURegs * const VU = (VURegs*)&VU0; + +//u32 vu0time = 0; +//static LARGE_INTEGER vu0base, vu0final; + +#ifdef PCSX2_DEVBUILD +extern u32 vudump; +#endif + +#define VF_VAL(x) ((x==0x80000000)?0:x) +static u32 vuprogcount = 0; +void iDumpVU0Registers() +{ + int i; + for(i = 1; i < 32; ++i) { + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]), + VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU0.VI[i].F); + else if( i == REG_MAC_FLAG ) __Log("%x\n", VU0.VI[i].UL&0xff); + else if( i == REG_STATUS_FLAG ) __Log("%x\n", VU0.VI[i].UL&0x03); + else if( i == REG_CLIP_FLAG ) __Log("0\n"); + else __Log("%x\n", VU0.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]); +} + +void recExecuteVU0Block( void ) +{ + //SysPrintf("executeVU0 %x\n", VU0.VI[ REG_TPC ].UL); + //QueryPerformanceCounter(&vu0base); + + assert( VU0.VI[REG_VPU_STAT].UL & 1 ); + +#ifdef _DEBUG + vuprogcount++; + +// __Log("VU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); + + //vudump |= 0x10; + //vudump |= 8; + + if( (vudump&8) && !CHECK_VU0REC ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + + ///while( (VU0.VI[ REG_VPU_STAT ].UL&1) ) { + if( CHECK_VU0REC) { + FreezeXMMRegs(1); + SuperVUExecuteProgram(VU0.VI[ REG_TPC ].UL, 0); + } + else { + intExecuteVU0Block(); + } + //} + +// __Log("eVU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); +// QueryPerformanceCounter(&vu0final); +// vu0time += (u32)(vu0final.QuadPart-vu0final.QuadPart); +} + +void recClearVU0( u32 Addr, u32 Size ) +{ + if( CHECK_VU0REC ) { + SuperVUClear(Addr, Size*4, 0); + } +} + +void (*recVU0_LOWER_OPCODE[128])() = { + recVU0MI_LQ , recVU0MI_SQ , recVU0unknown , recVU0unknown, + recVU0MI_ILW , recVU0MI_ISW , recVU0unknown , recVU0unknown, + recVU0MI_IADDIU, recVU0MI_ISUBIU, recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_FCEQ , recVU0MI_FCSET , recVU0MI_FCAND, recVU0MI_FCOR, /* 0x10 */ + recVU0MI_FSEQ , recVU0MI_FSSET , recVU0MI_FSAND, recVU0MI_FSOR, + recVU0MI_FMEQ , recVU0unknown , recVU0MI_FMAND, recVU0MI_FMOR, + recVU0MI_FCGET , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_B , recVU0MI_BAL , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0MI_JR , recVU0MI_JALR , recVU0unknown , recVU0unknown, + recVU0MI_IBEQ , recVU0MI_IBNE , recVU0unknown , recVU0unknown, + recVU0MI_IBLTZ , recVU0MI_IBGTZ , recVU0MI_IBLEZ, recVU0MI_IBGEZ, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x40*/ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x50 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x60 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x70 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, +}; + +void (*recVU0LowerOP_T3_00_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MOVE , recVU0MI_LQI , recVU0MI_DIV , recVU0MI_MTIR, + recVU0MI_RNEXT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_MFP , recVU0unknown , recVU0unknown, + recVU0MI_ESADD , recVU0MI_EATANxy, recVU0MI_ESQRT, recVU0MI_ESIN, +}; + +void (*recVU0LowerOP_T3_01_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MR32 , recVU0MI_SQI , recVU0MI_SQRT , recVU0MI_MFIR, + recVU0MI_RGET , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0MI_XITOP, recVU0unknown, + recVU0MI_ERSADD, recVU0MI_EATANxz, recVU0MI_ERSQRT, recVU0MI_EATAN, +}; + +void (*recVU0LowerOP_T3_10_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_LQD , recVU0MI_RSQRT, recVU0MI_ILWR, + recVU0MI_RINIT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ELENG , recVU0MI_ESUM , recVU0MI_ERCPR, recVU0MI_EEXP, +}; + +void (*recVU0LowerOP_T3_11_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_SQD , recVU0MI_WAITQ, recVU0MI_ISWR, + recVU0MI_RXOR , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ERLENG, recVU0unknown , recVU0MI_WAITP, recVU0unknown, +}; + +void (*recVU0LowerOP_OPCODE[64])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_IADD , recVU0MI_ISUB , recVU0MI_IADDI, recVU0unknown, /* 0x30 */ + recVU0MI_IAND , recVU0MI_IOR , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP_T3_00, recVU0LowerOP_T3_01, recVU0LowerOP_T3_10, recVU0LowerOP_T3_11, +}; + +void (*recVU0_UPPER_OPCODE[64])() = { + recVU0MI_ADDx , recVU0MI_ADDy , recVU0MI_ADDz , recVU0MI_ADDw, + recVU0MI_SUBx , recVU0MI_SUBy , recVU0MI_SUBz , recVU0MI_SUBw, + recVU0MI_MADDx , recVU0MI_MADDy , recVU0MI_MADDz , recVU0MI_MADDw, + recVU0MI_MSUBx , recVU0MI_MSUBy , recVU0MI_MSUBz , recVU0MI_MSUBw, + recVU0MI_MAXx , recVU0MI_MAXy , recVU0MI_MAXz , recVU0MI_MAXw, /* 0x10 */ + recVU0MI_MINIx , recVU0MI_MINIy , recVU0MI_MINIz , recVU0MI_MINIw, + recVU0MI_MULx , recVU0MI_MULy , recVU0MI_MULz , recVU0MI_MULw, + recVU0MI_MULq , recVU0MI_MAXi , recVU0MI_MULi , recVU0MI_MINIi, + recVU0MI_ADDq , recVU0MI_MADDq , recVU0MI_ADDi , recVU0MI_MADDi, /* 0x20 */ + recVU0MI_SUBq , recVU0MI_MSUBq , recVU0MI_SUBi , recVU0MI_MSUBi, + recVU0MI_ADD , recVU0MI_MADD , recVU0MI_MUL , recVU0MI_MAX, + recVU0MI_SUB , recVU0MI_MSUB , recVU0MI_OPMSUB, recVU0MI_MINI, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0_UPPER_FD_00, recVU0_UPPER_FD_01, recVU0_UPPER_FD_10, recVU0_UPPER_FD_11, +}; + +void (*recVU0_UPPER_FD_00_TABLE[32])() = { + recVU0MI_ADDAx, recVU0MI_SUBAx , recVU0MI_MADDAx, recVU0MI_MSUBAx, + recVU0MI_ITOF0, recVU0MI_FTOI0, recVU0MI_MULAx , recVU0MI_MULAq , + recVU0MI_ADDAq, recVU0MI_SUBAq, recVU0MI_ADDA , recVU0MI_SUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_01_TABLE[32])() = { + recVU0MI_ADDAy , recVU0MI_SUBAy , recVU0MI_MADDAy, recVU0MI_MSUBAy, + recVU0MI_ITOF4 , recVU0MI_FTOI4 , recVU0MI_MULAy , recVU0MI_ABS , + recVU0MI_MADDAq, recVU0MI_MSUBAq, recVU0MI_MADDA , recVU0MI_MSUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_10_TABLE[32])() = { + recVU0MI_ADDAz , recVU0MI_SUBAz , recVU0MI_MADDAz, recVU0MI_MSUBAz, + recVU0MI_ITOF12, recVU0MI_FTOI12, recVU0MI_MULAz , recVU0MI_MULAi , + recVU0MI_MADDAi, recVU0MI_SUBAi , recVU0MI_MULA , recVU0MI_OPMULA, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_11_TABLE[32])() = { + recVU0MI_ADDAw , recVU0MI_SUBAw , recVU0MI_MADDAw, recVU0MI_MSUBAw, + recVU0MI_ITOF15, recVU0MI_FTOI15, recVU0MI_MULAw , recVU0MI_CLIP , + recVU0MI_MADDAi, recVU0MI_MSUBAi, recVU0unknown , recVU0MI_NOP , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void recVU0_UPPER_FD_00( void ) +{ + recVU0_UPPER_FD_00_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_01( void ) +{ + recVU0_UPPER_FD_01_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_10( void ) +{ + recVU0_UPPER_FD_10_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_11( void ) +{ + recVU0_UPPER_FD_11_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP( void ) +{ + recVU0LowerOP_OPCODE[ VU0.code & 0x3f ]( ); +} + +void recVU0LowerOP_T3_00( void ) +{ + recVU0LowerOP_T3_00_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_01( void ) +{ + recVU0LowerOP_T3_01_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_10( void ) +{ + recVU0LowerOP_T3_10_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_11( void ) +{ + recVU0LowerOP_T3_11_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + + +void recVU0unknown( void ) +{ +#ifdef CPU_LOG + CPU_LOG("Unknown VU0 micromode opcode calledn"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +#ifdef RECOMPILE_VUMI_ABS +void recVU0MI_ABS() { recVUMI_ABS(VU, VUREC_INFO); } +#else +void recVU0MI_ABS() { REC_VUOP(VU0, ABS); } +#endif + +#ifdef RECOMPILE_VUMI_ADD +void recVU0MI_ADD() { recVUMI_ADD(VU, VUREC_INFO); } +void recVU0MI_ADDi() { recVUMI_ADDi(VU, VUREC_INFO); } +void recVU0MI_ADDq() { recVUMI_ADDq(VU, VUREC_INFO); } +void recVU0MI_ADDx() { recVUMI_ADDx(VU, VUREC_INFO); } +void recVU0MI_ADDy() { recVUMI_ADDy(VU, VUREC_INFO); } +void recVU0MI_ADDz() { recVUMI_ADDz(VU, VUREC_INFO); } +void recVU0MI_ADDw() { recVUMI_ADDw(VU, VUREC_INFO); } +#else +void recVU0MI_ADD() { REC_VUOP(VU0, ADD); } +void recVU0MI_ADDi() { REC_VUOP(VU0, ADDi); } +void recVU0MI_ADDq() { REC_VUOP(VU0, ADDq); } +void recVU0MI_ADDx() { REC_VUOP(VU0, ADDx); } +void recVU0MI_ADDy() { REC_VUOP(VU0, ADDy); } +void recVU0MI_ADDz() { REC_VUOP(VU0, ADDz); } +void recVU0MI_ADDw() { REC_VUOP(VU0, ADDw); } +#endif + +#ifdef RECOMPILE_VUMI_ADDA +void recVU0MI_ADDA() { recVUMI_ADDA(VU, VUREC_INFO); } +void recVU0MI_ADDAi() { recVUMI_ADDAi(VU, VUREC_INFO); } +void recVU0MI_ADDAq() { recVUMI_ADDAq(VU, VUREC_INFO); } +void recVU0MI_ADDAx() { recVUMI_ADDAx(VU, VUREC_INFO); } +void recVU0MI_ADDAy() { recVUMI_ADDAy(VU, VUREC_INFO); } +void recVU0MI_ADDAz() { recVUMI_ADDAz(VU, VUREC_INFO); } +void recVU0MI_ADDAw() { recVUMI_ADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_ADDA() { REC_VUOP(VU0, ADDA); } +void recVU0MI_ADDAi() { REC_VUOP(VU0, ADDAi); } +void recVU0MI_ADDAq() { REC_VUOP(VU0, ADDAq); } +void recVU0MI_ADDAx() { REC_VUOP(VU0, ADDAx); } +void recVU0MI_ADDAy() { REC_VUOP(VU0, ADDAy); } +void recVU0MI_ADDAz() { REC_VUOP(VU0, ADDAz); } +void recVU0MI_ADDAw() { REC_VUOP(VU0, ADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_SUB +void recVU0MI_SUB() { recVUMI_SUB(VU, VUREC_INFO); } +void recVU0MI_SUBi() { recVUMI_SUBi(VU, VUREC_INFO); } +void recVU0MI_SUBq() { recVUMI_SUBq(VU, VUREC_INFO); } +void recVU0MI_SUBx() { recVUMI_SUBx(VU, VUREC_INFO); } +void recVU0MI_SUBy() { recVUMI_SUBy(VU, VUREC_INFO); } +void recVU0MI_SUBz() { recVUMI_SUBz(VU, VUREC_INFO); } +void recVU0MI_SUBw() { recVUMI_SUBw(VU, VUREC_INFO); } +#else +void recVU0MI_SUB() { REC_VUOP(VU0, SUB); } +void recVU0MI_SUBi() { REC_VUOP(VU0, SUBi); } +void recVU0MI_SUBq() { REC_VUOP(VU0, SUBq); } +void recVU0MI_SUBx() { REC_VUOP(VU0, SUBx); } +void recVU0MI_SUBy() { REC_VUOP(VU0, SUBy); } +void recVU0MI_SUBz() { REC_VUOP(VU0, SUBz); } +void recVU0MI_SUBw() { REC_VUOP(VU0, SUBw); } +#endif + +#ifdef RECOMPILE_VUMI_SUBA +void recVU0MI_SUBA() { recVUMI_SUBA(VU, VUREC_INFO); } +void recVU0MI_SUBAi() { recVUMI_SUBAi(VU, VUREC_INFO); } +void recVU0MI_SUBAq() { recVUMI_SUBAq(VU, VUREC_INFO); } +void recVU0MI_SUBAx() { recVUMI_SUBAx(VU, VUREC_INFO); } +void recVU0MI_SUBAy() { recVUMI_SUBAy(VU, VUREC_INFO); } +void recVU0MI_SUBAz() { recVUMI_SUBAz(VU, VUREC_INFO); } +void recVU0MI_SUBAw() { recVUMI_SUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_SUBA() { REC_VUOP(VU0, SUBA); } +void recVU0MI_SUBAi() { REC_VUOP(VU0, SUBAi); } +void recVU0MI_SUBAq() { REC_VUOP(VU0, SUBAq); } +void recVU0MI_SUBAx() { REC_VUOP(VU0, SUBAx); } +void recVU0MI_SUBAy() { REC_VUOP(VU0, SUBAy); } +void recVU0MI_SUBAz() { REC_VUOP(VU0, SUBAz); } +void recVU0MI_SUBAw() { REC_VUOP(VU0, SUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MUL +void recVU0MI_MUL() { recVUMI_MUL(VU, VUREC_INFO); } +void recVU0MI_MULi() { recVUMI_MULi(VU, VUREC_INFO); } +void recVU0MI_MULq() { recVUMI_MULq(VU, VUREC_INFO); } +void recVU0MI_MULx() { recVUMI_MULx(VU, VUREC_INFO); } +void recVU0MI_MULy() { recVUMI_MULy(VU, VUREC_INFO); } +void recVU0MI_MULz() { recVUMI_MULz(VU, VUREC_INFO); } +void recVU0MI_MULw() { recVUMI_MULw(VU, VUREC_INFO); } +#else +void recVU0MI_MUL() { REC_VUOP(VU0, MUL); } +void recVU0MI_MULi() { REC_VUOP(VU0, MULi); } +void recVU0MI_MULq() { REC_VUOP(VU0, MULq); } +void recVU0MI_MULx() { REC_VUOP(VU0, MULx); } +void recVU0MI_MULy() { REC_VUOP(VU0, MULy); } +void recVU0MI_MULz() { REC_VUOP(VU0, MULz); } +void recVU0MI_MULw() { REC_VUOP(VU0, MULw); } +#endif + +#ifdef RECOMPILE_VUMI_MULA +void recVU0MI_MULA() { recVUMI_MULA(VU, VUREC_INFO); } +void recVU0MI_MULAi() { recVUMI_MULAi(VU, VUREC_INFO); } +void recVU0MI_MULAq() { recVUMI_MULAq(VU, VUREC_INFO); } +void recVU0MI_MULAx() { recVUMI_MULAx(VU, VUREC_INFO); } +void recVU0MI_MULAy() { recVUMI_MULAy(VU, VUREC_INFO); } +void recVU0MI_MULAz() { recVUMI_MULAz(VU, VUREC_INFO); } +void recVU0MI_MULAw() { recVUMI_MULAw(VU, VUREC_INFO); } +#else +void recVU0MI_MULA() { REC_VUOP(VU0, MULA); } +void recVU0MI_MULAi() { REC_VUOP(VU0, MULAi); } +void recVU0MI_MULAq() { REC_VUOP(VU0, MULAq); } +void recVU0MI_MULAx() { REC_VUOP(VU0, MULAx); } +void recVU0MI_MULAy() { REC_VUOP(VU0, MULAy); } +void recVU0MI_MULAz() { REC_VUOP(VU0, MULAz); } +void recVU0MI_MULAw() { REC_VUOP(VU0, MULAw); } +#endif + +#ifdef RECOMPILE_VUMI_MADD +void recVU0MI_MADD() { recVUMI_MADD(VU, VUREC_INFO); } +void recVU0MI_MADDi() { recVUMI_MADDi(VU, VUREC_INFO); } +void recVU0MI_MADDq() { recVUMI_MADDq(VU, VUREC_INFO); } +void recVU0MI_MADDx() { recVUMI_MADDx(VU, VUREC_INFO); } +void recVU0MI_MADDy() { recVUMI_MADDy(VU, VUREC_INFO); } +void recVU0MI_MADDz() { recVUMI_MADDz(VU, VUREC_INFO); } +void recVU0MI_MADDw() { recVUMI_MADDw(VU, VUREC_INFO); } +#else +void recVU0MI_MADD() { REC_VUOP(VU0, MADD); } +void recVU0MI_MADDi() { REC_VUOP(VU0, MADDi); } +void recVU0MI_MADDq() { REC_VUOP(VU0, MADDq); } +void recVU0MI_MADDx() { REC_VUOP(VU0, MADDx); } +void recVU0MI_MADDy() { REC_VUOP(VU0, MADDy); } +void recVU0MI_MADDz() { REC_VUOP(VU0, MADDz); } +void recVU0MI_MADDw() { REC_VUOP(VU0, MADDw); } +#endif + +#ifdef RECOMPILE_VUMI_MADDA +void recVU0MI_MADDA() { recVUMI_MADDA(VU, VUREC_INFO); } +void recVU0MI_MADDAi() { recVUMI_MADDAi(VU, VUREC_INFO); } +void recVU0MI_MADDAq() { recVUMI_MADDAq(VU, VUREC_INFO); } +void recVU0MI_MADDAx() { recVUMI_MADDAx(VU, VUREC_INFO); } +void recVU0MI_MADDAy() { recVUMI_MADDAy(VU, VUREC_INFO); } +void recVU0MI_MADDAz() { recVUMI_MADDAz(VU, VUREC_INFO); } +void recVU0MI_MADDAw() { recVUMI_MADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_MADDA() { REC_VUOP(VU0, MADDA); } +void recVU0MI_MADDAi() { REC_VUOP(VU0, MADDAi); } +void recVU0MI_MADDAq() { REC_VUOP(VU0, MADDAq); } +void recVU0MI_MADDAx() { REC_VUOP(VU0, MADDAx); } +void recVU0MI_MADDAy() { REC_VUOP(VU0, MADDAy); } +void recVU0MI_MADDAz() { REC_VUOP(VU0, MADDAz); } +void recVU0MI_MADDAw() { REC_VUOP(VU0, MADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUB +void recVU0MI_MSUB() { recVUMI_MSUB(VU, VUREC_INFO); } +void recVU0MI_MSUBi() { recVUMI_MSUBi(VU, VUREC_INFO); } +void recVU0MI_MSUBq() { recVUMI_MSUBq(VU, VUREC_INFO); } +void recVU0MI_MSUBx() { recVUMI_MSUBx(VU, VUREC_INFO); } +void recVU0MI_MSUBy() { recVUMI_MSUBy(VU, VUREC_INFO); } +void recVU0MI_MSUBz() { recVUMI_MSUBz(VU, VUREC_INFO); } +void recVU0MI_MSUBw() { recVUMI_MSUBw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUB() { REC_VUOP(VU0, MSUB); } +void recVU0MI_MSUBi() { REC_VUOP(VU0, MSUBi); } +void recVU0MI_MSUBq() { REC_VUOP(VU0, MSUBq); } +void recVU0MI_MSUBx() { REC_VUOP(VU0, MSUBx); } +void recVU0MI_MSUBy() { REC_VUOP(VU0, MSUBy); } +void recVU0MI_MSUBz() { REC_VUOP(VU0, MSUBz); } +void recVU0MI_MSUBw() { REC_VUOP(VU0, MSUBw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUBA +void recVU0MI_MSUBA() { recVUMI_MSUBA(VU, VUREC_INFO); } +void recVU0MI_MSUBAi() { recVUMI_MSUBAi(VU, VUREC_INFO); } +void recVU0MI_MSUBAq() { recVUMI_MSUBAq(VU, VUREC_INFO); } +void recVU0MI_MSUBAx() { recVUMI_MSUBAx(VU, VUREC_INFO); } +void recVU0MI_MSUBAy() { recVUMI_MSUBAy(VU, VUREC_INFO); } +void recVU0MI_MSUBAz() { recVUMI_MSUBAz(VU, VUREC_INFO); } +void recVU0MI_MSUBAw() { recVUMI_MSUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUBA() { REC_VUOP(VU0, MSUBA); } +void recVU0MI_MSUBAi() { REC_VUOP(VU0, MSUBAi); } +void recVU0MI_MSUBAq() { REC_VUOP(VU0, MSUBAq); } +void recVU0MI_MSUBAx() { REC_VUOP(VU0, MSUBAx); } +void recVU0MI_MSUBAy() { REC_VUOP(VU0, MSUBAy); } +void recVU0MI_MSUBAz() { REC_VUOP(VU0, MSUBAz); } +void recVU0MI_MSUBAw() { REC_VUOP(VU0, MSUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MAX +void recVU0MI_MAX() { recVUMI_MAX(VU, VUREC_INFO); } +void recVU0MI_MAXi() { recVUMI_MAXi(VU, VUREC_INFO); } +void recVU0MI_MAXx() { recVUMI_MAXx(VU, VUREC_INFO); } +void recVU0MI_MAXy() { recVUMI_MAXy(VU, VUREC_INFO); } +void recVU0MI_MAXz() { recVUMI_MAXz(VU, VUREC_INFO); } +void recVU0MI_MAXw() { recVUMI_MAXw(VU, VUREC_INFO); } +#else +void recVU0MI_MAX() { REC_VUOP(VU0, MAX); } +void recVU0MI_MAXi() { REC_VUOP(VU0, MAXi); } +void recVU0MI_MAXx() { REC_VUOP(VU0, MAXx); } +void recVU0MI_MAXy() { REC_VUOP(VU0, MAXy); } +void recVU0MI_MAXz() { REC_VUOP(VU0, MAXz); } +void recVU0MI_MAXw() { REC_VUOP(VU0, MAXw); } +#endif + +#ifdef RECOMPILE_VUMI_MINI +void recVU0MI_MINI() { recVUMI_MINI(VU, VUREC_INFO); } +void recVU0MI_MINIi() { recVUMI_MINIi(VU, VUREC_INFO); } +void recVU0MI_MINIx() { recVUMI_MINIx(VU, VUREC_INFO); } +void recVU0MI_MINIy() { recVUMI_MINIy(VU, VUREC_INFO); } +void recVU0MI_MINIz() { recVUMI_MINIz(VU, VUREC_INFO); } +void recVU0MI_MINIw() { recVUMI_MINIw(VU, VUREC_INFO); } +#else +void recVU0MI_MINI() { REC_VUOP(VU0, MINI); } +void recVU0MI_MINIi() { REC_VUOP(VU0, MINIi); } +void recVU0MI_MINIx() { REC_VUOP(VU0, MINIx); } +void recVU0MI_MINIy() { REC_VUOP(VU0, MINIy); } +void recVU0MI_MINIz() { REC_VUOP(VU0, MINIz); } +void recVU0MI_MINIw() { REC_VUOP(VU0, MINIw); } +#endif + +#ifdef RECOMPILE_VUMI_FTOI +void recVU0MI_FTOI0() { recVUMI_FTOI0(VU, VUREC_INFO); } +void recVU0MI_FTOI4() { recVUMI_FTOI4(VU, VUREC_INFO); } +void recVU0MI_FTOI12() { recVUMI_FTOI12(VU, VUREC_INFO); } +void recVU0MI_FTOI15() { recVUMI_FTOI15(VU, VUREC_INFO); } +void recVU0MI_ITOF0() { recVUMI_ITOF0(VU, VUREC_INFO); } +void recVU0MI_ITOF4() { recVUMI_ITOF4(VU, VUREC_INFO); } +void recVU0MI_ITOF12() { recVUMI_ITOF12(VU, VUREC_INFO); } +void recVU0MI_ITOF15() { recVUMI_ITOF15(VU, VUREC_INFO); } +#else +void recVU0MI_FTOI0() { REC_VUOP(VU0, FTOI0); } +void recVU0MI_FTOI4() { REC_VUOP(VU0, FTOI4); } +void recVU0MI_FTOI12() { REC_VUOP(VU0, FTOI12); } +void recVU0MI_FTOI15() { REC_VUOP(VU0, FTOI15); } +void recVU0MI_ITOF0() { REC_VUOP(VU0, ITOF0); } +void recVU0MI_ITOF4() { REC_VUOP(VU0, ITOF4); } +void recVU0MI_ITOF12() { REC_VUOP(VU0, ITOF12); } +void recVU0MI_ITOF15() { REC_VUOP(VU0, ITOF15); } +#endif + +void recVU0MI_OPMULA() { recVUMI_OPMULA(VU, VUREC_INFO); } +void recVU0MI_OPMSUB() { recVUMI_OPMSUB(VU, VUREC_INFO); } +void recVU0MI_NOP() { } +void recVU0MI_CLIP() { recVUMI_CLIP(VU, VUREC_INFO); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +#ifdef RECOMPILE_VUMI_MISC + +void recVU0MI_MTIR() { recVUMI_MTIR(VU, VUREC_INFO); } +void recVU0MI_MR32() { recVUMI_MR32(VU, VUREC_INFO); } +void recVU0MI_MFIR() { recVUMI_MFIR(VU, VUREC_INFO); } +void recVU0MI_MOVE() { recVUMI_MOVE(VU, VUREC_INFO); } +void recVU0MI_WAITQ() { recVUMI_WAITQ(VU, VUREC_INFO); } +void recVU0MI_MFP() { recVUMI_MFP(VU, VUREC_INFO); } +void recVU0MI_WAITP() { SysPrintf("vu0 wait p?\n"); } + +#else + +void recVU0MI_MOVE() { REC_VUOP(VU0, MOVE); } +void recVU0MI_MFIR() { REC_VUOP(VU0, MFIR); } +void recVU0MI_MTIR() { REC_VUOP(VU0, MTIR); } +void recVU0MI_MR32() { REC_VUOP(VU0, MR32); } +void recVU0MI_WAITQ() { } +void recVU0MI_MFP() { REC_VUOP(VU0, MFP); } +void recVU0MI_WAITP() { REC_VUOP(VU0, WAITP); } + +#endif + +#ifdef RECOMPILE_VUMI_MATH + +void recVU0MI_SQRT() { recVUMI_SQRT(VU, VUREC_INFO); } +void recVU0MI_RSQRT() { recVUMI_RSQRT(VU, VUREC_INFO); } +void recVU0MI_DIV() { recVUMI_DIV(VU, VUREC_INFO); } + +#else + +void recVU0MI_DIV() { REC_VUOP(VU0, DIV);} +void recVU0MI_SQRT() { REC_VUOP(VU0, SQRT); } +void recVU0MI_RSQRT() { REC_VUOP(VU0, RSQRT); } + +#endif + +#ifdef RECOMPILE_VUMI_E + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { recVUMI_ELENG(VU, VUREC_INFO); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#else + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { REC_VUOP(VU0, ELENG); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#endif + +#ifdef RECOMPILE_VUMI_X + +void recVU0MI_XITOP() { recVUMI_XITOP(VU, VUREC_INFO); } +void recVU0MI_XGKICK() { recVUMI_XGKICK(VU, VUREC_INFO); } +void recVU0MI_XTOP() { recVUMI_XTOP(VU, VUREC_INFO); } + +#else + +void recVU0MI_XITOP() { REC_VUOP(VU0, XITOP); } +void recVU0MI_XGKICK() { REC_VUOP(VU0, XGKICK);} +void recVU0MI_XTOP() { REC_VUOP(VU0, XTOP);} + +#endif + +#ifdef RECOMPILE_VUMI_RANDOM + +void recVU0MI_RINIT() { recVUMI_RINIT(VU, VUREC_INFO); } +void recVU0MI_RGET() { recVUMI_RGET(VU, VUREC_INFO); } +void recVU0MI_RNEXT() { recVUMI_RNEXT(VU, VUREC_INFO); } +void recVU0MI_RXOR() { recVUMI_RXOR(VU, VUREC_INFO); } + +#else + +void recVU0MI_RINIT() { REC_VUOP(VU0, RINIT); } +void recVU0MI_RGET() { REC_VUOP(VU0, RGET); } +void recVU0MI_RNEXT() { REC_VUOP(VU0, RNEXT); } +void recVU0MI_RXOR() { REC_VUOP(VU0, RXOR); } + +#endif + +#ifdef RECOMPILE_VUMI_FLAG + +void recVU0MI_FSAND() { recVUMI_FSAND(VU, VUREC_INFO); } +void recVU0MI_FSEQ() { recVUMI_FSEQ(VU, VUREC_INFO); } +void recVU0MI_FSOR() { recVUMI_FSOR(VU, VUREC_INFO); } +void recVU0MI_FSSET() { recVUMI_FSSET(VU, VUREC_INFO); } +void recVU0MI_FMEQ() { recVUMI_FMEQ(VU, VUREC_INFO); } +void recVU0MI_FMOR() { recVUMI_FMOR(VU, VUREC_INFO); } +void recVU0MI_FCEQ() { recVUMI_FCEQ(VU, VUREC_INFO); } +void recVU0MI_FCOR() { recVUMI_FCOR(VU, VUREC_INFO); } +void recVU0MI_FCSET() { recVUMI_FCSET(VU, VUREC_INFO); } +void recVU0MI_FCGET() { recVUMI_FCGET(VU, VUREC_INFO); } +void recVU0MI_FCAND() { recVUMI_FCAND(VU, VUREC_INFO); } +void recVU0MI_FMAND() { recVUMI_FMAND(VU, VUREC_INFO); } + +#else + +void recVU0MI_FSAND() { REC_VUOP(VU0, FSAND); } +void recVU0MI_FSEQ() { REC_VUOP(VU0, FSEQ); } +void recVU0MI_FSOR() { REC_VUOP(VU0, FSOR); } +void recVU0MI_FSSET() { REC_VUOP(VU0, FSSET); } +void recVU0MI_FMAND() { REC_VUOP(VU0, FMAND); } +void recVU0MI_FMEQ() { REC_VUOP(VU0, FMEQ); } +void recVU0MI_FMOR() { REC_VUOP(VU0, FMOR); } +void recVU0MI_FCAND() { REC_VUOP(VU0, FCAND); } +void recVU0MI_FCEQ() { REC_VUOP(VU0, FCEQ); } +void recVU0MI_FCOR() { REC_VUOP(VU0, FCOR); } +void recVU0MI_FCSET() { REC_VUOP(VU0, FCSET); } +void recVU0MI_FCGET() { REC_VUOP(VU0, FCGET); } + +#endif + +#ifdef RECOMPILE_VUMI_LOADSTORE + +void recVU0MI_LQ() { recVUMI_LQ(VU, VUREC_INFO); } +void recVU0MI_LQD() { recVUMI_LQD(VU, VUREC_INFO); } +void recVU0MI_LQI() { recVUMI_LQI(VU, VUREC_INFO); } +void recVU0MI_SQ() { recVUMI_SQ(VU, VUREC_INFO); } +void recVU0MI_SQD() { recVUMI_SQD(VU, VUREC_INFO); } +void recVU0MI_SQI() { recVUMI_SQI(VU, VUREC_INFO); } +void recVU0MI_ILW() { recVUMI_ILW(VU, VUREC_INFO); } +void recVU0MI_ISW() { recVUMI_ISW(VU, VUREC_INFO); } +void recVU0MI_ILWR() { recVUMI_ILWR(VU, VUREC_INFO); } +void recVU0MI_ISWR() { recVUMI_ISWR(VU, VUREC_INFO); } + +#else + +void recVU0MI_LQ() { REC_VUOP(VU0, LQ); } +void recVU0MI_LQD() { REC_VUOP(VU0, LQD); } +void recVU0MI_LQI() { REC_VUOP(VU0, LQI); } +void recVU0MI_SQ() { REC_VUOP(VU0, SQ); } +void recVU0MI_SQD() { REC_VUOP(VU0, SQD); } +void recVU0MI_SQI() { REC_VUOP(VU0, SQI); } +void recVU0MI_ILW() { REC_VUOP(VU0, ILW); } +void recVU0MI_ISW() { REC_VUOP(VU0, ISW); } +void recVU0MI_ILWR() { REC_VUOP(VU0, ILWR); } +void recVU0MI_ISWR() { REC_VUOP(VU0, ISWR); } + +#endif + +#ifdef RECOMPILE_VUMI_ARITHMETIC + +void recVU0MI_IADD() { recVUMI_IADD(VU, VUREC_INFO); } +void recVU0MI_IADDI() { recVUMI_IADDI(VU, VUREC_INFO); } +void recVU0MI_IADDIU() { recVUMI_IADDIU(VU, VUREC_INFO); } +void recVU0MI_IOR() { recVUMI_IOR(VU, VUREC_INFO); } +void recVU0MI_ISUB() { recVUMI_ISUB(VU, VUREC_INFO); } +void recVU0MI_IAND() { recVUMI_IAND(VU, VUREC_INFO); } +void recVU0MI_ISUBIU() { recVUMI_ISUBIU(VU, VUREC_INFO); } + +#else + +void recVU0MI_IADD() { REC_VUOP(VU0, IADD); } +void recVU0MI_IADDI() { REC_VUOP(VU0, IADDI); } +void recVU0MI_IADDIU() { REC_VUOP(VU0, IADDIU); } +void recVU0MI_IOR() { REC_VUOP(VU0, IOR); } +void recVU0MI_ISUB() { REC_VUOP(VU0, ISUB); } +void recVU0MI_IAND() { REC_VUOP(VU0, IAND); } +void recVU0MI_ISUBIU() { REC_VUOP(VU0, ISUBIU); } + +#endif + +#ifdef RECOMPILE_VUMI_BRANCH + +void recVU0MI_IBEQ() { recVUMI_IBEQ(VU, VUREC_INFO); } +void recVU0MI_IBGEZ() { recVUMI_IBGEZ(VU, VUREC_INFO); } +void recVU0MI_IBLTZ() { recVUMI_IBLTZ(VU, VUREC_INFO); } +void recVU0MI_IBLEZ() { recVUMI_IBLEZ(VU, VUREC_INFO); } +void recVU0MI_IBGTZ() { recVUMI_IBGTZ(VU, VUREC_INFO); } +void recVU0MI_IBNE() { recVUMI_IBNE(VU, VUREC_INFO); } +void recVU0MI_B() { recVUMI_B(VU, VUREC_INFO); } +void recVU0MI_BAL() { recVUMI_BAL(VU, VUREC_INFO); } +void recVU0MI_JR() { recVUMI_JR(VU, VUREC_INFO); } +void recVU0MI_JALR() { recVUMI_JALR(VU, VUREC_INFO); } + +#else + +void recVU0MI_IBEQ() { REC_VUOP(VU0, IBEQ); } +void recVU0MI_IBGEZ() { REC_VUOP(VU0, IBGEZ); } +void recVU0MI_IBGTZ() { REC_VUOP(VU0, IBGTZ); } +void recVU0MI_IBLTZ() { REC_VUOP(VU0, IBLTZ); } +void recVU0MI_IBLEZ() { REC_VUOP(VU0, IBLEZ); } +void recVU0MI_IBNE() { REC_VUOP(VU0, IBNE); } +void recVU0MI_B() { REC_VUOP(VU0, B); } +void recVU0MI_BAL() { REC_VUOP(VU0, BAL); } +void recVU0MI_JR() { REC_VUOP(VU0, JR); } +void recVU0MI_JALR() { REC_VUOP(VU0, JALR); } + +#endif + diff --git a/x86/iVU0micro.h b/x86/iVU0micro.h new file mode 100644 index 0000000000..b5c08c512f --- /dev/null +++ b/x86/iVU0micro.h @@ -0,0 +1,221 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU0MICRO_H__ +#define __IVU0MICRO_H__ + +void recResetVU0(); +void recExecuteVU0Block( void ); +void recClearVU0( u32 Addr, u32 Size ); + +extern void (*recVU0_LOWER_OPCODE[128])(); +extern void (*recVU0_UPPER_OPCODE[64])(); + +extern void (*recVU0_UPPER_FD_00_TABLE[32])(); +extern void (*recVU0_UPPER_FD_01_TABLE[32])(); +extern void (*recVU0_UPPER_FD_10_TABLE[32])(); +extern void (*recVU0_UPPER_FD_11_TABLE[32])(); + +void recVU0_UPPER_FD_00(); +void recVU0_UPPER_FD_01(); +void recVU0_UPPER_FD_10(); +void recVU0_UPPER_FD_11(); + +void recVU0LowerOP(); +void recVU0LowerOP_T3_00(); +void recVU0LowerOP_T3_01(); +void recVU0LowerOP_T3_10(); +void recVU0LowerOP_T3_11(); + +void recVU0unknown(); + + + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void recVU0MI_ABS(); +void recVU0MI_ADD(); +void recVU0MI_ADDi(); +void recVU0MI_ADDq(); +void recVU0MI_ADDx(); +void recVU0MI_ADDy(); +void recVU0MI_ADDz(); +void recVU0MI_ADDw(); +void recVU0MI_ADDA(); +void recVU0MI_ADDAi(); +void recVU0MI_ADDAq(); +void recVU0MI_ADDAx(); +void recVU0MI_ADDAy(); +void recVU0MI_ADDAz(); +void recVU0MI_ADDAw(); +void recVU0MI_SUB(); +void recVU0MI_SUBi(); +void recVU0MI_SUBq(); +void recVU0MI_SUBx(); +void recVU0MI_SUBy(); +void recVU0MI_SUBz(); +void recVU0MI_SUBw(); +void recVU0MI_SUBA(); +void recVU0MI_SUBAi(); +void recVU0MI_SUBAq(); +void recVU0MI_SUBAx(); +void recVU0MI_SUBAy(); +void recVU0MI_SUBAz(); +void recVU0MI_SUBAw(); +void recVU0MI_MUL(); +void recVU0MI_MULi(); +void recVU0MI_MULq(); +void recVU0MI_MULx(); +void recVU0MI_MULy(); +void recVU0MI_MULz(); +void recVU0MI_MULw(); +void recVU0MI_MULA(); +void recVU0MI_MULAi(); +void recVU0MI_MULAq(); +void recVU0MI_MULAx(); +void recVU0MI_MULAy(); +void recVU0MI_MULAz(); +void recVU0MI_MULAw(); +void recVU0MI_MADD(); +void recVU0MI_MADDi(); +void recVU0MI_MADDq(); +void recVU0MI_MADDx(); +void recVU0MI_MADDy(); +void recVU0MI_MADDz(); +void recVU0MI_MADDw(); +void recVU0MI_MADDA(); +void recVU0MI_MADDAi(); +void recVU0MI_MADDAq(); +void recVU0MI_MADDAx(); +void recVU0MI_MADDAy(); +void recVU0MI_MADDAz(); +void recVU0MI_MADDAw(); +void recVU0MI_MSUB(); +void recVU0MI_MSUBi(); +void recVU0MI_MSUBq(); +void recVU0MI_MSUBx(); +void recVU0MI_MSUBy(); +void recVU0MI_MSUBz(); +void recVU0MI_MSUBw(); +void recVU0MI_MSUBA(); +void recVU0MI_MSUBAi(); +void recVU0MI_MSUBAq(); +void recVU0MI_MSUBAx(); +void recVU0MI_MSUBAy(); +void recVU0MI_MSUBAz(); +void recVU0MI_MSUBAw(); +void recVU0MI_MAX(); +void recVU0MI_MAXi(); +void recVU0MI_MAXx(); +void recVU0MI_MAXy(); +void recVU0MI_MAXz(); +void recVU0MI_MAXw(); +void recVU0MI_MINI(); +void recVU0MI_MINIi(); +void recVU0MI_MINIx(); +void recVU0MI_MINIy(); +void recVU0MI_MINIz(); +void recVU0MI_MINIw(); +void recVU0MI_OPMULA(); +void recVU0MI_OPMSUB(); +void recVU0MI_NOP(); +void recVU0MI_FTOI0(); +void recVU0MI_FTOI4(); +void recVU0MI_FTOI12(); +void recVU0MI_FTOI15(); +void recVU0MI_ITOF0(); +void recVU0MI_ITOF4(); +void recVU0MI_ITOF12(); +void recVU0MI_ITOF15(); +void recVU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void recVU0MI_DIV(); +void recVU0MI_SQRT(); +void recVU0MI_RSQRT(); +void recVU0MI_IADD(); +void recVU0MI_IADDI(); +void recVU0MI_IADDIU(); +void recVU0MI_IAND(); +void recVU0MI_IOR(); +void recVU0MI_ISUB(); +void recVU0MI_ISUBIU(); +void recVU0MI_MOVE(); +void recVU0MI_MFIR(); +void recVU0MI_MTIR(); +void recVU0MI_MR32(); +void recVU0MI_LQ(); +void recVU0MI_LQD(); +void recVU0MI_LQI(); +void recVU0MI_SQ(); +void recVU0MI_SQD(); +void recVU0MI_SQI(); +void recVU0MI_ILW(); +void recVU0MI_ISW(); +void recVU0MI_ILWR(); +void recVU0MI_ISWR(); +void recVU0MI_RINIT(); +void recVU0MI_RGET(); +void recVU0MI_RNEXT(); +void recVU0MI_RXOR(); +void recVU0MI_WAITQ(); +void recVU0MI_FSAND(); +void recVU0MI_FSEQ(); +void recVU0MI_FSOR(); +void recVU0MI_FSSET(); +void recVU0MI_FMAND(); +void recVU0MI_FMEQ(); +void recVU0MI_FMOR(); +void recVU0MI_FCAND(); +void recVU0MI_FCEQ(); +void recVU0MI_FCOR(); +void recVU0MI_FCSET(); +void recVU0MI_FCGET(); +void recVU0MI_IBEQ(); +void recVU0MI_IBGEZ(); +void recVU0MI_IBGTZ(); +void recVU0MI_IBLEZ(); +void recVU0MI_IBLTZ(); +void recVU0MI_IBNE(); +void recVU0MI_B(); +void recVU0MI_BAL(); +void recVU0MI_JR(); +void recVU0MI_JALR(); +void recVU0MI_MFP(); +void recVU0MI_WAITP(); +void recVU0MI_ESADD(); +void recVU0MI_ERSADD(); +void recVU0MI_ELENG(); +void recVU0MI_ERLENG(); +void recVU0MI_EATANxy(); +void recVU0MI_EATANxz(); +void recVU0MI_ESUM(); +void recVU0MI_ERCPR(); +void recVU0MI_ESQRT(); +void recVU0MI_ERSQRT(); +void recVU0MI_ESIN(); +void recVU0MI_EATAN(); +void recVU0MI_EEXP(); +void recVU0MI_XITOP(); + +#endif /* __IVU0MICRO_H__ */ diff --git a/x86/iVU1micro.c b/x86/iVU1micro.c new file mode 100644 index 0000000000..27d23f956d --- /dev/null +++ b/x86/iVU1micro.c @@ -0,0 +1,201 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VU.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +// TODO: there's a bug in spyro start menu where release vurec works but debug vurec breaks + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +#define VU ((VURegs*)&VU1) + +u32 vu1recpcold = -1; +u32 vu1reccountold = -1; + +static _vuopinfo _opinfo[256]; + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU1.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU1.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU1.code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU1.code>>24) & 0x1) +#define _Y ((VU1.code>>23) & 0x1) +#define _Z ((VU1.code>>22) & 0x1) +#define _W ((VU1.code>>21) & 0x1) + +#define _Fsf_ ((VU1.code >> 21) & 0x03) +#define _Ftf_ ((VU1.code >> 23) & 0x03) + + +#define VU1_VFx_ADDR(x) (u32)&VU1.VF[x].UL[0] +#define VU1_VFy_ADDR(x) (u32)&VU1.VF[x].UL[1] +#define VU1_VFz_ADDR(x) (u32)&VU1.VF[x].UL[2] +#define VU1_VFw_ADDR(x) (u32)&VU1.VF[x].UL[3] + +#define VU1_REGR_ADDR (u32)&VU1.VI[REG_R] +#define VU1_REGI_ADDR (u32)&VU1.VI[REG_I] +#define VU1_REGQ_ADDR (u32)&VU1.VI[REG_Q] +#define VU1_REGMAC_ADDR (u32)&VU1.VI[REG_MAC_FLAG] + +#define VU1_VI_ADDR(x) (u32)&VU1.VI[x].UL + +#define VU1_ACCx_ADDR (u32)&VU1.ACC.UL[0] +#define VU1_ACCy_ADDR (u32)&VU1.ACC.UL[1] +#define VU1_ACCz_ADDR (u32)&VU1.ACC.UL[2] +#define VU1_ACCw_ADDR (u32)&VU1.ACC.UL[3] + +static void VU1RecompileBlock(void); + +void recVU1Init() +{ + SuperVUInit(1); +} + +void recVU1Shutdown() +{ + SuperVUDestroy(1); +} + +void recResetVU1( void ) { + + if( CHECK_VU1REC ) { + SuperVUReset(1); + } + + vu1recpcold = 0; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +static void iDumpBlock() +{ + FILE *f; + char filename[ 256 ]; + u32 *mem; + u32 i; + +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#endif + SysPrintf( "dump1 %x => %x (%s)\n", VU1.VI[ REG_TPC ].UL, pc, filename ); + + f = fopen( filename, "wb" ); + for ( i = VU1.VI[REG_TPC].UL; i < pc; i += 8 ) { + char* pstr; + mem = (u32*)&VU1.Micro[i]; + + pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%x: %-40s ", i, pstr); + + pstr = disVU1MicroLF( mem[0], i ); + fprintf(f, "%s\n", pstr); + } + fclose( f ); +} + +#define VF_VAL(x) ((x==0x80000000)?0:x) + +void iDumpVU1Registers() +{ + int i; + for(i = 1; i < 32; ++i) { + //__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]); + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), + VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F); + //else __Log("%x\n", VU1.VI[i].UL); + else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG)?0:VU1.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]); +} + +#ifdef PCSX2_DEVBUILD +static u32 vuprogcount = 0, vutotal = 0; +u32 vudump = 0; +#endif + +extern u32 g_sseMXCSR; +void recExecuteVU1Block(void) +{ +#ifdef _DEBUG + int i; + __asm stmxcsr i + assert( g_sseMXCSR == (i&~0x3f) ); +#endif + + if (CHECK_VU1REC) + { + if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + + assert( (VU1.VI[ REG_TPC ].UL&7) == 0 ); + +#ifdef _DEBUG + vuprogcount++; +#endif + + SuperVUExecuteProgram(VU1.VI[ REG_TPC ].UL, 1); + assert( !(VU0.VI[ REG_VPU_STAT ].UL&0x100) ); + } + else { + intExecuteVU1Block(); + } +} + +void recClearVU1( u32 Addr, u32 Size ) { + assert( (Addr&7) == 0 ); + + if( CHECK_VU1REC ) { + SuperVUClear(Addr, Size*4, 1); + } +} diff --git a/x86/iVU1micro.h b/x86/iVU1micro.h new file mode 100644 index 0000000000..cd83b5c3f3 --- /dev/null +++ b/x86/iVU1micro.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU1MICRO_H__ +#define __IVU1MICRO_H__ + +void recVU1Init(); +void recVU1Shutdown(); +void recResetVU1(); +void recExecuteVU1Block( void ); +void recClearVU1( u32 Addr, u32 Size ); + +extern u32 vudump; +void iDumpVU1Registers(); + +#endif /* __IVU1MICRO_H__ */ diff --git a/x86/iVUmicro.c b/x86/iVUmicro.c new file mode 100644 index 0000000000..a040a99f13 --- /dev/null +++ b/x86/iVUmicro.c @@ -0,0 +1,4541 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +int vucycle; +int vucycleold; +_vuopinfo *cinfo = NULL; + +//Lower/Upper instructions can use that.. +#define _Ft_ (( VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ (( VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ (( VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X (( VU->code>>24) & 0x1) +#define _Y (( VU->code>>23) & 0x1) +#define _Z (( VU->code>>22) & 0x1) +#define _W (( VU->code>>21) & 0x1) + +#define _XYZW_SS (_X+_Y+_Z+_W==1) + +#define _Fsf_ (( VU->code >> 21) & 0x03) +#define _Ftf_ (( VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + +#define VU_VFx_ADDR(x) (int)&VU->VF[x].UL[0] +#define VU_VFy_ADDR(x) (int)&VU->VF[x].UL[1] +#define VU_VFz_ADDR(x) (int)&VU->VF[x].UL[2] +#define VU_VFw_ADDR(x) (int)&VU->VF[x].UL[3] + +#define VU_REGR_ADDR (int)&VU->VI[REG_R] +#define VU_REGQ_ADDR (int)&VU->VI[REG_Q] +#define VU_REGMAC_ADDR (int)&VU->VI[REG_MAC_FLAG] + +#define VU_VI_ADDR(x, read) GetVIAddr(VU, x, read, info) + +#define VU_ACCx_ADDR (int)&VU->ACC.UL[0] +#define VU_ACCy_ADDR (int)&VU->ACC.UL[1] +#define VU_ACCz_ADDR (int)&VU->ACC.UL[2] +#define VU_ACCw_ADDR (int)&VU->ACC.UL[3] + +#define _X_Y_Z_W ((( VU->code >> 21 ) & 0xF ) ) + +__declspec(align(16)) float recMult_float_to_int4[4] = { 16.0, 16.0, 16.0, 16.0 }; +__declspec(align(16)) float recMult_float_to_int12[4] = { 4096.0, 4096.0, 4096.0, 4096.0 }; +__declspec(align(16)) float recMult_float_to_int15[4] = { 32768.0, 32768.0, 32768.0, 32768.0 }; + +__declspec(align(16)) float recMult_int_to_float4[4] = { 0.0625f, 0.0625f, 0.0625f, 0.0625f }; +__declspec(align(16)) float recMult_int_to_float12[4] = { 0.000244140625, 0.000244140625, 0.000244140625, 0.000244140625 }; +__declspec(align(16)) float recMult_int_to_float15[4] = { 0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125 }; +static s32 bpc; +_VURegsNum* g_VUregs = NULL; +u8 g_MACFlagTransform[256] = {0}; // used to flip xyzw bits + +static int SSEmovMask[ 16 ][ 4 ] = +{ +{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +{ 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } +}; + +#define VU_SWAPSRC 0xf090 // don't touch + +#define _vuIsRegSwappedWithTemp() (VU_SWAPSRC & (1<<_X_Y_Z_W)) + +// use for allocating vi regs +#define ALLOCTEMPX86(mode) _allocX86reg(-1, X86TYPE_TEMP, 0, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ALLOCVI(vi, mode) _allocX86reg(-1, X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), vi, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ADD_VI_NEEDED(vi) _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), vi); + +// 1 - src, 0 - dest wzyx +void VU_MERGE0(int dest, int src) { // 0000 +} +void VU_MERGE1(int dest, int src) { // 1000 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc4); +} +void VU_MERGE2(int dest, int src) { // 0100 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x64); +} +void VU_MERGE3(int dest, int src) { // 1100 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE4(int dest, int src) { // 0010s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE5(int dest, int src) { // 1010 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xd8); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd8); +} +void VU_MERGE6(int dest, int src) { // 0110 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x9c); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x78); +} +void VU_MERGE7(int dest, int src) { // 1110s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE8(int dest, int src) { // 0001 + SSE_MOVSS_XMM_to_XMM(dest, src); +} +void VU_MERGE9(int dest, int src) { // 1001 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc9); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd2); +} +void VU_MERGE10(int dest, int src) { // 0101 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x8d); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x72); +} +void VU_MERGE11(int dest, int src) { // 1101 + SSE_MOVSS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE12(int dest, int src) { // 0011s + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE13(int dest, int src) { // 1011s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0x64); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE14(int dest, int src) { // 0111s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xc4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE15(int dest, int src) { // 1111s + SSE_MOVAPS_XMM_to_XMM(dest, src); +} + +typedef void (*VUMERGEFN)(int dest, int src); +static VUMERGEFN s_VuMerge[16] = { + VU_MERGE0, VU_MERGE1, VU_MERGE2, VU_MERGE3, + VU_MERGE4, VU_MERGE5, VU_MERGE6, VU_MERGE7, + VU_MERGE8, VU_MERGE9, VU_MERGE10, VU_MERGE11, + VU_MERGE12, VU_MERGE13, VU_MERGE14, VU_MERGE15 }; + +#define VU_MERGE_REGS(dest, src) { \ + if( dest != src ) s_VuMerge[_X_Y_Z_W](dest, src); \ +} \ + +#define VU_MERGE_REGS_CUSTOM(dest, src, xyzw) { \ + if( dest != src ) s_VuMerge[xyzw](dest, src); \ +} \ + +void _unpackVF_xyzw(int dstreg, int srcreg, int xyzw) +{ + // don't use pshufd + if( dstreg == srcreg || !cpucaps.hasStreamingSIMD3Extensions) { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + switch (xyzw) { + case 0: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x00); break; + case 1: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); break; + case 2: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xaa); break; + case 3: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); break; + } + } + else { + switch (xyzw) { + case 0: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 1: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 2: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + case 3: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + } + } +} + +void _unpackVFSS_xyzw(int dstreg, int srcreg, int xyzw) +{ + switch (xyzw) { + case 0: + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + break; + case 1: + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); + } + break; + case 2: + SSE_MOVHLPS_XMM_to_XMM(dstreg, srcreg); + break; + case 3: + if( cpucaps.hasStreamingSIMD3Extensions && dstreg != srcreg ) { + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + } + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); + } + break; + } +} + +void _vuFlipRegSS(VURegs * VU, int reg) +{ + assert( _XYZW_SS ); + if( _Y ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xe1); + else if( _Z ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xc6); + else if( _W ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0x27); +} + +void _vuMoveSS(VURegs * VU, int dstreg, int srcreg) +{ + assert( _XYZW_SS ); + if( _Y ) _unpackVFSS_xyzw(dstreg, srcreg, 1); + else if( _Z ) _unpackVFSS_xyzw(dstreg, srcreg, 2); + else if( _W ) _unpackVFSS_xyzw(dstreg, srcreg, 3); + else _unpackVFSS_xyzw(dstreg, srcreg, 0); +} + +void _recvuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((vucycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing FMAC pipe[%d]\n", i); } +#endif + VU->fmac[i].enable = 0; + } + } +} + +void _recvuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((vucycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->fdiv.enable = 0; + } +} + +void _recvuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((vucycle - VU->efu.sCycle) >= VU->efu.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->efu.enable = 0; + } +} + +void _recvuTestPipes(VURegs * VU) { + _recvuFMACflush(VU); + _recvuFDIVflush(VU); + _recvuEFUflush(VU); +} + +void _recvuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + u32 mask = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + (VU->fmac[i].xyzw & xyzw)) break; + } + + if (i == 8) return; + + // do a perchannel delay + // old code + cycle = VU->fmac[i].Cycle - (vucycle - VU->fmac[i].sCycle); + VU->fmac[i].enable = 0; + + // new code +// mask = VU->fmac[i].xyzw & xyzw; +// if( mask & 1 ) mask = 4; // w +// else if( mask & 2 ) mask = 3; // z +// else if( mask & 4 ) mask = 2; // y +// else if( mask & 8 ) mask = 1; // x +// +// assert( (int)VU->fmac[i].sCycle < (int)vucycle ); +// cycle = 0; +// if( vucycle - VU->fmac[i].sCycle < mask ) +// cycle = mask - (vucycle - VU->fmac[i].sCycle); +// +// VU->fmac[i].xyzw &= ~xyzw; +// if( !VU->fmac[i].xyzw ) +// VU->fmac[i].enable = 0; + +// SysPrintf("FMAC stall %d\n", cycle); + vucycle+= cycle; + _recvuTestPipes(VU); +} + +void _recvuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { + SysPrintf("*PCSX2*: error , out of fmacs\n"); + } + +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding FMAC pipe[%d]; reg %d\n", i, reg); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = vucycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].reg = reg; +} + +void _recvuFDIVAdd(VURegs * VU, int cycles) { +// SysPrintf("adding FDIV pipe\n"); + VU->fdiv.enable = 1; + VU->fdiv.sCycle = vucycle; + VU->fdiv.Cycle = cycles; +} + +void _recvuEFUAdd(VURegs * VU, int cycles) { +// SysPrintf("adding EFU pipe\n"); + VU->efu.enable = 1; + VU->efu.sCycle = vucycle; + VU->efu.Cycle = cycles; +} + +void _recvuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + + if( VUregsn->VFread0 && (VUregsn->VFread0 == VUregsn->VFread1) ) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw|VUregsn->VFr1xyzw); + } + else { + if (VUregsn->VFread0) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _recvuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } + } +} + +void _recvuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _recvuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { +// SysPrintf("REG_CLIP_FLAG pipe\n"); + _recvuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _recvuFMACAdd(VU, 0, 0); + } +} + +void _recvuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (vucycle - VU->fdiv.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->fdiv.enable = 0; + vucycle+= cycle; +} + +void _recvuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (vucycle - VU->efu.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->efu.enable = 0; + vucycle+= cycle; +} + +void _recvuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushFDIV(VU); +} + +void _recvuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushEFU(VU); +} + +void _recvuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_Q)) { + _recvuFDIVAdd(VU, VUregsn->cycles); + } +} + +void _recvuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_P)) { + _recvuEFUAdd(VU, VUregsn->cycles); + } +} + +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + } +} + +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuTestEFUStalls(VU, VUregsn); break; + } +} + +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + } +} + +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuAddEFUStalls(VU, VUregsn); break; + } +} + + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs) +{ + _VURegsNum* lregs; + _VURegsNum* uregs; + int *ptr; + + lregs = pCodeRegs; + uregs = pCodeRegs+1; + + ptr = (int*)&VU->Micro[pc]; + pc += 8; + + if (ptr[1] & 0x40000000) { // EOP + branch |= 8; + } + + VU->code = ptr[1]; + if (VU == &VU1) { + VU1regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } else { + VU0regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } + + _recvuTestUpperStalls(VU, uregs); + switch(VU->code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3d: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3e: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3f: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + + if (uregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (uregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + info->cycle = vucycle; + memset(lregs, 0, sizeof(lregs)); + } else { + + VU->code = ptr[0]; + if (VU == &VU1) { + VU1regs_LOWER_OPCODE[VU->code >> 25](lregs); + } else { + VU0regs_LOWER_OPCODE[VU->code >> 25](lregs); + } + + _recvuTestLowerStalls(VU, lregs); + info->cycle = vucycle; + + if (lregs->pipe == VUPIPE_BRANCH) { + branch |= 1; + } + + if (lregs->VIwrite & (1 << REG_Q)) { + info->q |= 4; + info->cycles = lregs->cycles; + info->pqinst = (VU->code&2)>>1; // rsqrt is 2 + } + else if (lregs->pipe == VUPIPE_FDIV) { + info->q |= 8|1; + info->pqinst = 0; + } + + if (lregs->VIwrite & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 4; + info->cycles = lregs->cycles; + + switch( VU->code & 0xff ) { + case 0xfd: info->pqinst = 0; break; //eatan + case 0x7c: info->pqinst = 0; break; //eatanxy + case 0x7d: info->pqinst = 0; break; //eatanzy + case 0xfe: info->pqinst = 1; break; //eexp + case 0xfc: info->pqinst = 2; break; //esin + case 0x3f: info->pqinst = 3; break; //erleng + case 0x3e: info->pqinst = 4; break; //eleng + case 0x3d: info->pqinst = 4; break; //ersadd + case 0xbd: info->pqinst = 4; break; //ersqrt + case 0xbe: info->pqinst = 5; break; //ercpr + case 0xbc: info->pqinst = 5; break; //esqrt + case 0x7e: info->pqinst = 5; break; //esum + case 0x3c: info->pqinst = 6; break; //esadd + default: assert(0); + } + } + else if (lregs->pipe == VUPIPE_EFU) { + info->p |= 8|1; + } + + if (lregs->VIread & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_READ; + if (lregs->VIread & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_READ; + + if (lregs->VIwrite & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_WRITE; + if (lregs->VIwrite & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_WRITE; + + if (lregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (lregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + _recvuAddLowerStalls(VU, lregs); + } + _recvuAddUpperStalls(VU, uregs); + + _recvuTestPipes(VU); + + vucycle++; +} + +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs) +{ + int info = 0; + int vfread0=-1, vfread1 = -1, vfwrite = -1, vfacc = -1, vftemp=-1; + + assert( regs != NULL ); + + if( regs->VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<VFread0 ) vfread0 = _allocVFtoXMMreg(VU, -1, regs->VFread0, MODE_READ); + else if( regs->VIread & (1<VFread1 ) vfread1 = _allocVFtoXMMreg(VU, -1, regs->VFread1, MODE_READ); + else if( (regs->VIread & (1<VFr1xyzw != 0xff) vfread1 = _allocVFtoXMMreg(VU, -1, 0, MODE_READ); + + if( regs->VIread & (1<VIwrite&(1<VIwrite & (1<VFwxyzw != 0xf?MODE_READ:0)); + } + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwrite, MODE_WRITE|(regs->VFwxyzw != 0xf?MODE_READ:0)); + } + + if( vfacc>= 0 ) info |= PROCESS_EE_SET_ACC(vfacc); + if( vfwrite >= 0 ) { + if( regs->VFwrite == _Ft_ && vfread1 < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite); + } + else { + assert( regs->VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite); + } + } + + if( vfread0 >= 0 ) info |= PROCESS_EE_SET_S(vfread0); + if( vfread1 >= 0 ) info |= PROCESS_EE_SET_T(vfread1); + + vftemp = _allocTempXMMreg(XMMT_FPS, -1); + info |= PROCESS_VU_SET_TEMP(vftemp); + + if( regs->VIwrite & (1 << REG_CLIP_FLAG) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + int t1reg = _allocTempXMMreg(XMMT_FPS, -1); + int t2reg = _allocTempXMMreg(XMMT_FPS, -1); + + info |= PROCESS_EE_SET_D(t1reg); + info |= PROCESS_EE_SET_ACC(t2reg); + + _freeXMMreg(t1reg); // don't need + _freeXMMreg(t2reg); // don't need + } + else if( regs->VIwrite & (1<statusflag & 1 ) info |= PROCESS_VU_UPDATEFLAGS; + if( cinfo->macflag & 1) info |= PROCESS_VU_UPDATEFLAGS; + + if( regs->pipe == 0xff ) info |= PROCESS_VU_COP2; + + return info; +} + +// returns the correct VI addr +u32 GetVIAddr(VURegs * VU, int reg, int read, int info) +{ + if( info & PROCESS_VU_SUPER ) return SuperVUGetVIAddr(reg, read); + if( info & PROCESS_VU_COP2 ) return (u32)&VU->VI[reg].UL; + + if( read != 1 ) { + if( reg == REG_MAC_FLAG ) return (u32)&VU->macflag; + if( reg == REG_CLIP_FLAG ) return (u32)&VU->clipflag; + if( reg == REG_STATUS_FLAG ) return (u32)&VU->statusflag; + if( reg == REG_Q ) return (u32)&VU->q; + if( reg == REG_P ) return (u32)&VU->p; + } + + return (u32)&VU->VI[reg].UL; +} + +// gets a temp reg that is not EEREC_TEMP +int _vuGetTempXMMreg(int info) +{ + int t1reg = -1; + + if( _hasFreeXMMreg() ) { + t1reg = _allocTempXMMreg(XMMT_FPS, -1); + if( t1reg == EEREC_TEMP && _hasFreeXMMreg() ) { + int t = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t1reg); + t1reg = t; + _freeXMMreg(t1reg); + } + else { + _freeXMMreg(t1reg); + t1reg = -1; + } + } + + return t1reg; +} + +__declspec(align(16)) u32 g_minvals[4] = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}; +__declspec(align(16)) u32 g_maxvals[4] = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}; + +static __declspec(align(16)) int const_clip[] = { + 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + +static __declspec(align(16)) u32 s_FloatMinMax[] = { + 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, + 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, + 0, 0, 0, 0 }; + +static __declspec(align(16)) float s_fones[] = { 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f }; +static __declspec(align(16)) u32 s_mask[] = {0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff }; +static __declspec(align(16)) u32 s_expmask[] = {0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000}; + +void CheckForOverflowSS_(int fdreg, int t0reg) +{ + assert( t0reg != fdreg ); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDSS_XMM_to_XMM(t0reg, fdreg); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVSS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNESS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow_(int fdreg, int t0reg) +{ +// SSE_MAXPS_M128_to_XMM(fdreg, (u32)g_minvals); +// SSE_MINPS_M128_to_XMM(fdreg, (u32)g_maxvals); + + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, fdreg); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVAPS_M128_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNEPS_M128_to_XMM(t0reg, (u32)s_expmask); +// //SSE_ORPS_M128_to_XMM(t0reg, (u32)g_minvals); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow(int info, int regd) +{ + if( CHECK_FORCEABS && EEREC_TEMP != regd) { + // changing the order produces different results (tektag) + CheckForOverflow_(regd, EEREC_TEMP); + } +} + +// if unordered replaces with 0x7f7fffff (note, loses sign) +void ClampUnordered(int regd, int t0reg, int dosign) +{ + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, regd); + SSE_ANDPS_XMM_to_XMM(regd, t0reg); + SSE_ANDNPS_M128_to_XMM(t0reg, (u32)g_maxvals); + SSE_ORPS_XMM_to_XMM(regd, t0reg); +} + +// VU Flags +// NOTE: flags don't compute under/over flows since it is highly unlikely +// that games used them. Including them will lower performance. +void recUpdateFlags(VURegs * VU, int reg, int info) +{ + u32 flagmask; + u8* pjmp; + u32 macaddr, stataddr, prevstataddr; + int x86macflag, x86newflag, x86oldflag; + const static u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + if( !(info & PROCESS_VU_UPDATEFLAGS) ) + return; + + flagmask = macarr[_X_Y_Z_W]; + macaddr = VU_VI_ADDR(REG_MAC_FLAG, 0); + stataddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + assert( stataddr != 0); + prevstataddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + // 20 insts + x86newflag = ALLOCTEMPX86(MODE_8BITREG); + x86macflag = ALLOCTEMPX86(0); + x86oldflag = ALLOCTEMPX86(0); + + // can do with 8 bits since only computing zero/sign flags + if( EEREC_TEMP != reg ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_CMPEQPS_XMM_to_XMM(EEREC_TEMP, reg); + + MOV32MtoR(x86oldflag, prevstataddr); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + XOR32RtoR(EAX, EAX); + + SSE_ANDNPS_XMM_to_XMM(EEREC_TEMP, reg); // necessary! + + AND32ItoR(x86newflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + SSE_MOVMSKPS_XMM_to_R32(x86macflag, EEREC_TEMP); // sign + + SHL32ItoR(x86newflag, 4); + AND32ItoR(x86macflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + OR32RtoR(x86macflag, x86newflag); + } + else { + SSE_MOVMSKPS_XMM_to_R32(x86macflag, reg); // mask is < 0 (including 80000000) + + MOV32MtoR(x86oldflag, prevstataddr); + XOR32RtoR(EAX, EAX); + + SSE_CMPEQPS_M128_to_XMM(EEREC_TEMP, (u32)&s_FloatMinMax[8]); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + NOT32R(x86newflag); + AND32RtoR(x86macflag, x86newflag); + + AND32ItoR(x86macflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + NOT32R(x86newflag); + + AND32ItoR(x86newflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + SHL32ItoR(x86newflag, 4); + OR32RtoR(x86macflag, x86newflag); + } + + // x86macflag - new untransformed mac flag, EAX - new status bits, x86oldflag - old status flag + // x86macflag = zero_wzyx | sign_wzyx + MOV8RmtoROffset(x86newflag, x86macflag, (u32)g_MACFlagTransform); // transform + //MOV16RmSOffsettoR(x86newflag, x86macflag, (u32)g_MACFlagTransform, 1); + MOV32RtoR(x86macflag, x86oldflag); + SHL32ItoR(x86macflag, 6); + MOV8RtoM(macaddr, x86newflag); + OR32RtoR(x86oldflag, x86macflag); + + AND32ItoR(x86oldflag, 0x0c0); + OR32RtoR(x86oldflag, EAX); + MOV32RtoM(stataddr, x86oldflag); + + _freeX86reg(x86macflag); + _freeX86reg(x86newflag); + _freeX86reg(x86oldflag); +} + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +static __declspec(align(16)) int const_abs_table[16][4] = +{ + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, +}; + +void recVUMI_ABS(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_T, (int)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + } +} + +__declspec(align(16)) float s_two[4] = {0,0,0,2}; + +void recVUMI_ADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_two); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_two); + } + } + else { + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_ADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Ft_ == 0 && xyzw < 3 ) { + // just move + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if( _Fs_ == 0 && !_W ) { + // just move + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADDi(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDq(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDx(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 0, info); } +void recVUMI_ADDy(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 1, info); } +void recVUMI_ADDz(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 2, info); } +void recVUMI_ADDw(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 3, info); } + +void recVUMI_ADDA(VURegs *VU, int info) +{ + if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + assert( EEREC_ACC != EEREC_TEMP ); + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_ACC, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( _Fs_ == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_ACC, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDAi(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDAq(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDAx(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 0, info); } +void recVUMI_ADDAy(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 1, info); } +void recVUMI_ADDAz(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 2, info); } +void recVUMI_ADDAw(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 3, info); } + +void recVUMI_SUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Ft_ > 0 || _W ) SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + // neopets works better with this? + //CheckForOverflow(info, EEREC_D); +} + +void recVUMI_SUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if (EEREC_D != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +static __declspec(align(16)) s_unaryminus[4] = {0x80000000, 0, 0, 0}; + +void recVUMI_SUB_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_T ) { + if( _Fs_ > 0 ) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)s_unaryminus); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } +// else if( _XYZW_SS && xyzw == 0 ) { +// if( EEREC_D == EEREC_S ) { +// if( EEREC_D == EEREC_T ) { +// SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } +// else if( EEREC_D == EEREC_T ) { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_SUBi(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBq(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBx(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 0, info); } +void recVUMI_SUBy(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 1, info); } +void recVUMI_SUBz(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 2, info); } +void recVUMI_SUBw(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 3, info); } + +void recVUMI_SUBA(VURegs *VU, int info) +{ + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_ACC, (u32)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_ACC); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBAi(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBAq(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBAx(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 0, info); } +void recVUMI_SUBAy(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 1, info); } +void recVUMI_SUBAz(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 2, info); } +void recVUMI_SUBAw(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 3, info); } + +void recVUMI_MUL_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W == 1 && (_Ft_ == 0 || _Fs_==0) ) { // W + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, _Ft_ ? EEREC_T : EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( _Fd_ == _Fs_ && _Fs_ == _Ft_ && _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_D); + _vuFlipRegSS(VU, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (regd == EEREC_S) SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + } + } +} + +void recVUMI_MUL_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _XYZW_SS ) { + if( regd == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( regd == EEREC_S ) { + _vuFlipRegSS(VU, regd); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, regd); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + if( xyzw < 3 ) { + if (_X_Y_Z_W != 0xf) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + SSE_XORPS_XMM_to_XMM(regd, regd); + } + } + else { + assert(xyzw==3); + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( regd != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + } + else { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MUL_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MUL_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MULi(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULq(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULx(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 0, info); } +void recVUMI_MULy(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 1, info); } +void recVUMI_MULz(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 2, info); } +void recVUMI_MULw(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 3, info); } + +void recVUMI_MULA( VURegs *VU, int info ) +{ + recVUMI_MUL_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_iq(VURegs *VU, int addr, int info) +{ + recVUMI_MUL_iq_toD(VU, addr, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_xyzw(VURegs *VU, int xyzw, int info) +{ + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULAi(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULAq(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULAx(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 0, info); } +void recVUMI_MULAy(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 1, info); } +void recVUMI_MULAz(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 2, info); } +void recVUMI_MULAw(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 3, info); } + +void recVUMI_MADD_toD(VURegs *VU, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } +} + +void recVUMI_MADD_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + if( _Fs_ == 0 ) { + // add addr to w + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + else { + assert( EEREC_TEMP < XMMREGS ); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else if( regd == EEREC_S ) { + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else { + if( _Fs_ == 0 ) { + // add addr to w + if( _W ) { + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + + return; + } + + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + + if( xyzw == 3 ) { + // just add + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_S ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_S); + } + } + else { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_S ) SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_S); + } + } + } + } + else { + // just move acc to regd + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + + return; + } + + if( _X_Y_Z_W == 8 ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if( regd == EEREC_ACC ) { + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + // fixes suikoden 5 chars + CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MADDi(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MADDq(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MADDx(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 0, info); } +void recVUMI_MADDy(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 1, info); } +void recVUMI_MADDz(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 2, info); } +void recVUMI_MADDw(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 3, info); } + +void recVUMI_MADDA( VURegs *VU, int info ) +{ + recVUMI_MADD_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAi( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_VI_ADDR(REG_I, 1), EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAq( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_REGQ_ADDR, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAx( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 0, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAy( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 1, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAz( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 2, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAw( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 3, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUB_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_S ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_T ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_temp_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_iq_toD(VURegs *VU, int regd, int addr, int info) +{ + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB_xyzw_toD(VURegs *VU, int regd, int xyzw, int info) +{ + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_iq_toD(VU, EEREC_D, addr, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MSUBi(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MSUBq(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MSUBx(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 0, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBy(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 1, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBz(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 2, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBw(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 3, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBA( VURegs *VU, int info ) +{ + recVUMI_MSUB_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAi( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_VI_ADDR(REG_I, 1), info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAq( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_REGQ_ADDR, info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAx( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 0, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAy( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 1, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAz( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 2, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAw( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 3, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MAX(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MAX_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MAX_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + else if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + } + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + else SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_fones); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } +} + +void recVUMI_MAXi(VURegs *VU, int info) { recVUMI_MAX_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MAXx(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 0, info); } +void recVUMI_MAXy(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 1, info); } +void recVUMI_MAXz(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 2, info); } +void recVUMI_MAXw(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 3, info); } + +void recVUMI_MINI(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_T, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_S, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MINI_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINI_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINIi(VURegs *VU, int info) { recVUMI_MINI_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MINIx(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 0, info); } +void recVUMI_MINIy(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 1, info); } +void recVUMI_MINIz(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 2, info); } +void recVUMI_MINIw(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 3, info); } + +void recVUMI_OPMULA( VURegs *VU, int info ) +{ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xD2); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T ); + + VU_MERGE_REGS_CUSTOM(EEREC_ACC, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_ACC ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_OPMSUB( VURegs *VU, int info ) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM( EEREC_T, EEREC_T, 0xD2 ); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T); + + // negate and add + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS_CUSTOM(EEREC_D, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_D ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_NOP( VURegs *VU, int info ) +{ +} + +void recVUMI_FTOI0(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_FTOIX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if (EEREC_T != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + } +} + +void recVUMI_FTOI4( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int4[0], info); } +void recVUMI_FTOI12( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int12[0], info); } +void recVUMI_FTOI15( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int15[0], info); } + +void recVUMI_ITOF0( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + } + } +} + +void recVUMI_ITOFX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + } + + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + } +} + +void recVUMI_ITOF4( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float4[0], info); } +void recVUMI_ITOF12( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float12[0], info); } +void recVUMI_ITOF15( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float15[0], info); } + +void recVUMI_CLIP(VURegs *VU, int info) +{ + int t1reg = EEREC_D; + int t2reg = EEREC_ACC; + int x86temp0, x86temp1; + + u32 clipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + u32 prevclipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 2); + + assert( clipaddr != 0 ); + assert( t1reg != t2reg && t1reg != EEREC_TEMP && t2reg != EEREC_TEMP ); + + x86temp1 = ALLOCTEMPX86(MODE_8BITREG); + x86temp0 = ALLOCTEMPX86(0); + + if( _Ft_ == 0 ) { + // all 1s + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)&s_fones[0]); + SSE_MOVAPS_M128_to_XMM(t1reg, (u32)&s_fones[4]); + + MOV32MtoR(EAX, prevclipaddr); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, 3); + SSE_XORPS_XMM_to_XMM(t1reg, t1reg); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)const_clip); + + MOV32MtoR(EAX, prevclipaddr); + + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + } + + SSE_CMPLTPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_CMPNLEPS_XMM_to_XMM(t1reg, EEREC_S); + + SHL32ItoR(EAX, 6); + + SSE_MOVAPS_XMM_to_XMM(t2reg, EEREC_TEMP); + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, t1reg); + SSE_UNPCKHPS_XMM_to_XMM(t2reg, t1reg); + SSE_MOVMSKPS_XMM_to_R32(x86temp0, EEREC_TEMP); // -y,+y,-x,+x + SSE_MOVMSKPS_XMM_to_R32(x86temp1, t2reg); // -w,+w,-z,+z + + AND32ItoR(EAX, 0xffffff); + + AND8ItoR(x86temp1, 0x3); + SHL32ItoR(x86temp1, 4); + OR32RtoR(EAX, x86temp0); + OR32RtoR(EAX, x86temp1); + + MOV32RtoM(clipaddr, EAX); + if( !(info&(PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) MOV32RtoM((u32)&VU->VI[REG_CLIP_FLAG], EAX); + + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void recVUMI_DIV(VURegs *VU, int info) +{ + if( _Fs_ == 0 ) { + + if( _Ft_ == 0 ) { + if( _Fsf_ < 3 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0); + else if( _Ftf_ < 0 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x7f7fffff); + else MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x3f800000); + return; + } + + if( _Fsf_ == 3 ) { // = 1 + // don't use RCPSS (very bad precision) + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + + if( _Ftf_ == 0 || (xmmregs[EEREC_T].mode & MODE_WRITE) ) { + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Ft_].UL[_Ftf_]); + } + } + else { // = 0 + MOV32ItoR(VU_VI_ADDR(REG_Q, 0), 0); + return; + } + } + else { + if( _Fsf_ == 0 ) SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + // revert + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_SQRT( VURegs *VU, int info ) +{ + if( _Ftf_ ) { + if( xmmregs[EEREC_T].mode & MODE_WRITE ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Ft_].UL[_Ftf_]); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_RSQRT(VURegs *VU, int info) +{ + if( _Ftf_ ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + if( _Fs_ == 0 ) { + if( _Fsf_ == 3 ) SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void _addISIMMtoIT(VURegs *VU, s16 imm, int info) +{ + int fsreg = -1, ftreg; + if (_Ft_ == 0) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32ItoR(ftreg, imm&0xffff); + return; + } + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if (ftreg == fsreg) { + if (imm != 0 ) { + ADD16ItoR(ftreg, imm); + } + } else { + if( imm ) LEA16RtoR(ftreg, fsreg, imm); + else MOV32RtoR(ftreg, fsreg); + } +} + +void recVUMI_IADDI(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code >> 6 ) & 0x1f; + imm = ( imm & 0x10 ? 0xfff0 : 0) | ( imm & 0xf ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADDIU(VURegs *VU, int info) +{ + int imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADD( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else { + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) ADD32RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) ADD32RtoR(fdreg, fsreg); + else LEA16RRtoR(fdreg, fsreg, ftreg); + MOVZX32R16toR(fdreg, fdreg); // neeed since don't know if fdreg's upper bits are 0 + } +} + +void recVUMI_IAND( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Fs_ == 0 ) || ( _Ft_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) AND16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) AND16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, ftreg); + AND32RtoR(fdreg, fsreg); + } +} + +void recVUMI_IOR( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) OR16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) OR16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, fsreg); + OR32RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUB( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + NEG16R(fdreg); + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) SUB16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) { + SUB16RtoR(fdreg, fsreg); + NEG16R(fdreg); + } + else { + MOV32RtoR(fdreg, fsreg); + SUB16RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUBIU( VURegs *VU, int info ) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + imm = -imm; + _addISIMMtoIT(VU, (u32)imm & 0xffff, info); +} + +void recVUMI_MOVE( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_MFIR( VURegs *VU, int info ) +{ + static u32 s_temp; + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, 1); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _XYZW_SS ) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + _vuFlipRegSS(VU, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + SSE2_MOVD_M32_to_XMM(EEREC_T, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_T, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } + else { + MOVSX32M16toR(EAX, VU_VI_ADDR(_Fs_, 1)); + MOV32RtoM((u32)&s_temp, EAX); + + if( _X_Y_Z_W != 0xf ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, (u32)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } +} + +void recVUMI_MTIR( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, 2); + + if( _Fsf_ == 0 ) { + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_S); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_TEMP); + } + + AND32ItoM(VU_VI_ADDR(_Ft_, 0), 0xffff); +} + +void recVUMI_MR32( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x39); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x39); + } +} + +// if x86reg < 0, reads directly from offset +void _loadEAX(VURegs *VU, int x86reg, u32 offset, int info) +{ + if( x86reg >= 0 ) { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_RmOffset_to_XMM(EEREC_T, x86reg, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + + case 8: // X + SSE_MOVSS_RmOffset_to_XMM(EEREC_TEMP, x86reg, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_RmOffset_to_XMM(EEREC_T, x86reg, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_T, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_T, x86reg, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } + else { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_M64_to_XMM(EEREC_T, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + case 8: // X + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_M64_to_XMM(EEREC_T, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_T, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_T, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } +} + +int recVUTransformAddr(int x86reg, VURegs* VU, int vireg, int imm) +{ + u8* pjmp[2]; + if( x86reg == EAX ) { + if (imm) ADD32ItoR(x86reg, imm); + } + else { + if( imm ) LEA32RtoR(EAX, x86reg, imm); + else MOV32RtoR(EAX, x86reg); + } + + if( VU == &VU1 ) { + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0x3fff); + } + else { + // if addr >= 4200, reads integers + CMP32ItoR(EAX, 0x420); + pjmp[0] = JL8(0); + AND32ItoR(EAX, 0x1f); + SHL32ItoR(EAX, 2); + OR32ItoR(EAX, 0x4200); + + pjmp[1] = JMP8(0); + x86SetJ8(pjmp[0]); + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0xfff); // can be removed + + x86SetJ8(pjmp[1]); + } + + return EAX; +} + +void recVUMI_LQ(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + if (_Fs_ == 0) { + _loadEAX(VU, -1, (u32)GET_VU_MEM(VU, (u32)imm*16), info); + } else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, imm), (u32)VU->Mem, info); + } +} + +void recVUMI_LQD( VURegs *VU, int info ) +{ + int fsreg; + + if ( _Fs_ != 0 ) { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + SUB16ItoR( fsreg, 1 ); + } + + if ( _Ft_ == 0 ) return; + + if ( _Fs_ == 0 ) { + _loadEAX(VU, -1, (u32)VU->Mem, info); + } else { + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (u32)VU->Mem, info); + } +} + +void recVUMI_LQI(VURegs *VU, int info) +{ + int fsreg; + + if ( _Ft_ == 0 ) { + if( _Fs_ != 0 ) { + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_WRITE|MODE_READ)) >= 0 ) { + ADD16ItoR(fsreg, 1); + } + else { + ADD16ItoM( VU_VI_ADDR( _Fs_, 0 ), 1 ); + } + } + return; + } + + if (_Fs_ == 0) { + _loadEAX(VU, -1, (u32)VU->Mem, info); + } else { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (u32)VU->Mem, info); + ADD16ItoR( fsreg, 1 ); + } +} + +void _saveEAX(VURegs *VU, int x86reg, u32 offset, int info) +{ + int t1reg; + + if( _Fs_ == 0 ) { + if( _XYZW_SS ) { + u32 c = _W ? 0x3f800000 : 0; + if( x86reg >= 0 ) MOV32ItoRmOffset(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0)))); + else MOV32ItoM(offset+(_W?12:(_Z?8:(_Y?4:0))), c); + } + else { + int zeroreg = (x86reg == EAX) ? ALLOCTEMPX86(0) : EAX; + + XOR32RtoR(zeroreg, zeroreg); + if( x86reg >= 0 ) { + if( _X ) MOV32RtoRmOffset(x86reg, zeroreg, offset); + if( _Y ) MOV32RtoRmOffset(x86reg, zeroreg, offset+4); + if( _Z ) MOV32RtoRmOffset(x86reg, zeroreg, offset+8); + if( _W ) MOV32ItoRmOffset(x86reg, 0x3f800000, offset+12); + } + else { + if( _X ) MOV32RtoM(offset, zeroreg); + if( _Y ) MOV32RtoM(offset+4, zeroreg); + if( _Z ) MOV32RtoM(offset+8, zeroreg); + if( _W ) MOV32ItoM(offset+12, 0x3f800000); + } + + if( zeroreg != EAX ) _freeX86reg(zeroreg); + } + return; + } + + switch(_X_Y_Z_W) { + case 1: // W + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + break; + case 2: // Z + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + else SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + break; + case 3: // ZW + if( x86reg >= 0 ) SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8); + else SSE_MOVHPS_XMM_to_M64(offset+8, EEREC_S); + break; + case 4: // Y + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVSS_XMM_to_M32(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + break; + case 6: // YZ + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xc9); + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVLPS_XMM_to_M64(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xd2); + break; + case 8: // X + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + break; + case 9: // XW + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP); + + break; + case 12: // XY + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + break; + + case 14: // XYZ + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) { + SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + } + else { + SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + } + break; + case 15: // XYZW + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_S); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + } + break; + default: + + // EEREC_D is a temp reg + // find the first nonwrite reg + t1reg = _vuGetTempXMMreg(info); + + if( t1reg < 0 ) { + for(t1reg = 0; t1reg < XMMREGS; ++t1reg) { + if( xmmregs[t1reg].inuse && !(xmmregs[t1reg].mode&MODE_WRITE) ) break; + } + + if( t1reg == XMMREGS ) t1reg = -1; + else { + if( t1reg != EEREC_S ) _allocTempXMMreg(XMMT_FPS, t1reg); + } + } + + if( t1reg >= 0 ) { + // found a temp reg + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + if( t1reg != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + + VU_MERGE_REGS(EEREC_TEMP, t1reg); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + } + + if( t1reg != EEREC_S ) _freeXMMreg(t1reg); + else { + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (u32)&VU->VF[_Fs_]); + } + } + else { + // do it with one reg + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + VU_MERGE_REGS(EEREC_TEMP, EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + } + + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (u32)&VU->VF[_Fs_]); + } + + break; + } +} + +void recVUMI_SQ(VURegs *VU, int info) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if ( _Ft_ == 0 ) { + _saveEAX(VU, -1, (u32)GET_VU_MEM(VU, (int)imm * 16), info); + } + else { + int ftreg = ALLOCVI(_Ft_, MODE_READ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, imm), (u32)VU->Mem, info); + } +} + +void recVUMI_SQD(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (u32)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + SUB16ItoR( ftreg, 1 ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (u32)VU->Mem, info); + } +} + +void recVUMI_SQI(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (u32)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (u32)VU->Mem, info); + + ADD16ItoR( ftreg, 1 ); + } +} + +void recVUMI_ILW(VURegs *VU, int info) +{ + int ftreg; + s16 imm, off; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (u32)GET_VU_MEM(VU, (int)imm * 16 + off) ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (u32)VU->Mem + off); + } +} + +void recVUMI_ISW( VURegs *VU, int info ) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + + if (_Fs_ == 0) { + u32 off = (u32)GET_VU_MEM(VU, (int)imm * 16); + int ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_X) MOV32RtoM(off, ftreg); + if (_Y) MOV32RtoM(off+4, ftreg); + if (_Z) MOV32RtoM(off+8, ftreg); + if (_W) MOV32RtoM(off+12, ftreg); + } + else { + int x86reg, fsreg, ftreg; + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, imm); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+12); + } +} + +void recVUMI_ILWR( VURegs *VU, int info ) +{ + int off, ftreg; + + if ( _Ft_ == 0 ) return; + + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (int)VU->Mem + off ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (int)VU->Mem + off); + } +} + +void recVUMI_ISWR( VURegs *VU, int info ) +{ + int ftreg; + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_Fs_ == 0) { + if (_X) MOV32RtoM((int)VU->Mem, ftreg); + if (_Y) MOV32RtoM((int)VU->Mem+4, ftreg); + if (_Z) MOV32RtoM((int)VU->Mem+8, ftreg); + if (_W) MOV32RtoM((int)VU->Mem+12, ftreg); + } + else { + int x86reg; + int fsreg = ALLOCVI(_Fs_, MODE_READ); + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, 0); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+12); + } +} + +void recVUMI_RINIT(VURegs *VU, int info) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 2); + + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + MOV32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR( rreg, 0x7f << 23 ); + } +} + +void recVUMI_RGET(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + + if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +void recVUMI_RNEXT( VURegs *VU, int info ) +{ + int rreg, x86temp0, x86temp1; + if ( _Ft_ == 0) return; + + rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + x86temp0 = ALLOCTEMPX86(0); + x86temp1 = ALLOCTEMPX86(0); + + // code from www.project-fao.org + MOV32MtoR(rreg, VU_REGR_ADDR); + MOV32RtoR(x86temp0, rreg); + SHR32ItoR(x86temp0, 4); + AND32ItoR(x86temp0, 1); + + MOV32RtoR(x86temp1, rreg); + SHR32ItoR(x86temp1, 22); + AND32ItoR(x86temp1, 1); + + SHL32ItoR(rreg, 1); + XOR32RtoR(x86temp0, x86temp1); + XOR32RtoR(rreg, x86temp0); + AND32ItoR(rreg, 0x7fffff); + OR32ItoR(rreg, 0x3f800000); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); + + recVUMI_RGET(VU, info); +} + +void recVUMI_RXOR( VURegs *VU, int info ) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode & MODE_NOFLUSH) ) { + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_XORPS_M128_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + XOR32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR ( rreg, 0x3f800000 ); + } +} + +void recVUMI_WAITQ( VURegs *VU, int info ) +{ +// if( info & PROCESS_VU_SUPER ) { +// //CALLFunc(waitqfn); +// SuperVUFlush(0, 1); +// } +} + +void recVUMI_FSAND( VURegs *VU, int info ) +{ + int ftreg; + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32MtoR(ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1)); + AND32ItoR( ftreg, 0xFFF&imm ); +} + +void recVUMI_FSEQ( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if ( _Ft_ == 0 ) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + + MOVZX32M16toR( EAX, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + XOR32RtoR(ftreg, ftreg); + AND16ItoR( EAX, 0xFFF ); + + CMP16ItoR(EAX, imm); + SETE8R(ftreg); +} + +void recVUMI_FSOR( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if(_Ft_ == 0) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M16toR( ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + OR16ItoR( ftreg, imm ); +} + +void recVUMI_FSSET(VURegs *VU, int info) +{ + u32 writeaddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + u32 prevaddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + + MOV32MtoR(EAX, prevaddr); + AND32ItoR(EAX, 0x3f); + if ((imm&0xfc0) != 0) OR32ItoR(EAX, imm & 0xFC0); + + MOV32RtoM(writeaddr ? writeaddr : prevaddr, EAX); +} + +void recVUMI_FMAND( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( ftreg != fsreg ) MOVZX32R16toR(ftreg, fsreg); + } + else MOVZX32M16toR(ftreg, VU_VI_ADDR(_Fs_, 1)); + + AND16MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); +} + +void recVUMI_FMEQ( VURegs *VU, int info ) +{ + int ftreg, fsreg; + if ( _Ft_ == 0 ) return; + + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); + CMP16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(EAX); + MOVZX32R8toR(ftreg, EAX); + } + else { + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + fsreg = ALLOCVI(_Fs_, MODE_READ); + + XOR32RtoR(ftreg, ftreg); + + CMP16MtoR(fsreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(ftreg); + } +} + +void recVUMI_FMOR( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ); + OR16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + else { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M16toR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + OR16RtoR( ftreg, fsreg); + } + else { + OR16MtoR( ftreg, VU_VI_ADDR(_Fs_, 1)); + } + } +} + +void recVUMI_FCAND( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + XOR32RtoR(ftreg, ftreg); + AND32ItoR( EAX, VU->code & 0xFFFFFF ); + SETNZ8R(ftreg); +} + +void recVUMI_FCEQ( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + CMP32ItoR( EAX, VU->code&0xffffff ); + SETE8R(ftreg); +} + +void recVUMI_FCOR( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + OR32ItoR( EAX, (VU->code & 0xFFFFFF)|0xff000000 ); + ADD32ItoR(EAX, 1); + + // set to 1 if EAX is 0 + SETZ8R(ftreg); +} + +void recVUMI_FCSET( VURegs *VU, int info ) +{ + u32 addr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + + MOV32ItoM(addr ? addr : VU_VI_ADDR(REG_CLIP_FLAG, 2), VU->code&0xffffff ); + + if( !(info & (PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) + MOV32ItoM( VU_VI_ADDR(REG_CLIP_FLAG, 1), VU->code&0xffffff ); +} + +void recVUMI_FCGET( VURegs *VU, int info ) +{ + int ftreg; + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOV32MtoR(ftreg, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + AND32ItoR(ftreg, 0x0fff); +} + +// SuperVU branch fns are in ivuzerorec.cpp +static s32 _recbranchAddr(VURegs * VU) +{ + bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void recVUMI_IBEQ(VURegs *VU, int info) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBNE( VURegs *VU, int info ) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_B(VURegs *VU, int info) +{ + // supervu will take care of the rest + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + branch |= 3; +} + +void recVUMI_BAL( VURegs *VU, int info ) +{ + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_JR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + branch |= 3; +} + +void recVUMI_JALR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_MFP(VURegs *VU, int info) +{ + if (_Ft_ == 0) return; + + if( _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_T); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +static __declspec(align(16)) float s_tempmem[4]; + +void recVUMI_WAITP(VURegs *VU, int info) +{ +// if( info & PROCESS_VU_SUPER ) +// SuperVUFlush(1, 1); +} + +// in all EFU insts, EEREC_D is a temp reg +void vuSqSumXYZ(int regd, int regs, int regtemp) +{ + SSE_MOVAPS_XMM_to_XMM(regtemp, regs); + SSE_MULPS_XMM_to_XMM(regtemp, regtemp); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(regd, regtemp); + SSE_ADDPS_XMM_to_XMM(regd, regtemp); // regd.z = x+y+z + SSE_MOVHLPS_XMM_to_XMM(regd, regd); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(regd, regtemp); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + SSE_SHUFPS_XMM_to_XMM(regtemp, regtemp, 0x55); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + } +} + +void recVUMI_ESADD( VURegs *VU, int info) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_TEMP, EEREC_S, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERSADD( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + // almost same as vuSqSumXYZ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); // EEREC_D.z = x+y+z + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_D); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + } + + // don't use RCPSS (very bad precision) + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ELENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERLENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_EATANxy( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((u32)&s_tempmem[0]); + FLD32((u32)&s_tempmem[1]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[0]); + FLD32((u32)&VU->VF[_Fs_].UL[1]); + } + + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATANxz( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((u32)&s_tempmem[0]); + FLD32((u32)&s_tempmem[2]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[0]); + FLD32((u32)&VU->VF[_Fs_].UL[2]); + } + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_ESUM( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); // y+w, x+z + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); // y+w, y+w, x+z, x+z + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + } + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERCPR( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + + // don't use RCPSS (very bad precision) + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + // revert + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERSQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESIN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FLD32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + FSIN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATAN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FLD32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + } + + FLD1(); + FLD32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EEXP( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + FLDL2E(); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FMUL32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FMUL32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + // basically do 2^(log_2(e) * val) + FLD(0); + FRNDINT(); + FXCH(1); + FSUB32Rto0(1); + F2XM1(); + FLD1(); + FADD320toR(1); + FSCALE(); + FSTP(1); + + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_XITOP( VURegs *VU, int info ) +{ + int ftreg; + if (_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (int)&VU->vifRegs->itop ); +} + +void recVUMI_XTOP( VURegs *VU, int info ) +{ + int ftreg; + if ( _Ft_ == 0 ) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (int)&VU->vifRegs->top ); +} + +extern HANDLE g_hGsEvent; + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) +{ + u32 size; + u8* pmem; + u32* data = (u32*)((u8*)pMem + (addr&0x3fff)); + + size = GSgifTransferDummy(0, data, 0x4000>>4); + + size = 0x4000-(size<<4); + pmem = GSRingBufCopy(NULL, size, GS_RINGTYPE_P1); + assert( pmem != NULL ); + + memcpy_amd(pmem, (u8*)pMem+addr, size); + GSRINGBUF_DONECOPY(pmem, size); + + if( !CHECK_DUALCORE ) { + SetEvent(g_hGsEvent); + } +} + +//extern u32 vudump; +//void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 766 ) +// vudump |= 8; +//} + +void recVUMI_XGKICK( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _freeX86reg(fsreg); + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + + PUSH32R(fsreg); + PUSH32I((int)VU->Mem); + iFlushCall(FLUSH_NOCONST); + + //CALLFunc((u32)countfn); + + if( CHECK_MULTIGS ) { + CALLFunc((int)VU1XGKICK_MTGSTransfer); + ADD32ItoR(ESP, 8); + } + else { + CALLFunc((int)GSgifTransfer1); + } +} diff --git a/x86/iVUmicro.h b/x86/iVUmicro.h new file mode 100644 index 0000000000..2e38d50b08 --- /dev/null +++ b/x86/iVUmicro.h @@ -0,0 +1,274 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVUMICRO_H__ +#define __IVUMICRO_H__ + +#define VU0_MEMSIZE 0x1000 +#define VU1_MEMSIZE 0x4000 + +#define RECOMPILE_VUMI_ABS +#define RECOMPILE_VUMI_SUB +#define RECOMPILE_VUMI_SUBA +#define RECOMPILE_VUMI_MADD +#define RECOMPILE_VUMI_MADDA +#define RECOMPILE_VUMI_MSUB +#define RECOMPILE_VUMI_MSUBA + +#define RECOMPILE_VUMI_ADD +#define RECOMPILE_VUMI_ADDA +#define RECOMPILE_VUMI_MUL +#define RECOMPILE_VUMI_MULA +#define RECOMPILE_VUMI_MAX +#define RECOMPILE_VUMI_MINI +#define RECOMPILE_VUMI_FTOI + +#define RECOMPILE_VUMI_MATH +#define RECOMPILE_VUMI_MISC +#define RECOMPILE_VUMI_E +#define RECOMPILE_VUMI_X +#define RECOMPILE_VUMI_RANDOM +#define RECOMPILE_VUMI_FLAG +#define RECOMPILE_VUMI_BRANCH +#define RECOMPILE_VUMI_ARITHMETIC +#define RECOMPILE_VUMI_LOADSTORE + +#ifdef __x86_64__ +#undef RECOMPILE_VUMI_X +#endif + +u32 GetVIAddr(VURegs * VU, int reg, int read, int info); // returns the correct VI addr +void recUpdateFlags(VURegs * VU, int reg, int info); + +void _recvuTestPipes(VURegs * VU); +void _recvuFlushFDIV(VURegs * VU); +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +#define VUOP_READ 2 +#define VUOP_WRITE 4 + +// save on mem +typedef struct { + int cycle; + int cycles; + u8 statusflag; + u8 macflag; + u8 clipflag; + u8 dummy; + u8 q; + u8 p; + u16 pqinst; // bit of instruction specifying index (srec only) +} _vuopinfo; +extern _vuopinfo *cinfo; + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs); + +// allocates all the necessary regs and returns the indices +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs); + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr); // used for MTGS in XGKICK + +extern _VURegsNum* g_VUregs; + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; +#define VUREC_INFO eeVURecompileCode(VU, g_VUregs) + +extern int vucycle; +extern int vucycleold; + + +/***************************************** + VU Micromode Upper instructions +*****************************************/ + +void recVUMI_ABS(VURegs *vuRegs, int info); +void recVUMI_ADD(VURegs *vuRegs, int info); +void recVUMI_ADDi(VURegs *vuRegs, int info); +void recVUMI_ADDq(VURegs *vuRegs, int info); +void recVUMI_ADDx(VURegs *vuRegs, int info); +void recVUMI_ADDy(VURegs *vuRegs, int info); +void recVUMI_ADDz(VURegs *vuRegs, int info); +void recVUMI_ADDw(VURegs *vuRegs, int info); +void recVUMI_ADDA(VURegs *vuRegs, int info); +void recVUMI_ADDAi(VURegs *vuRegs, int info); +void recVUMI_ADDAq(VURegs *vuRegs, int info); +void recVUMI_ADDAx(VURegs *vuRegs, int info); +void recVUMI_ADDAy(VURegs *vuRegs, int info); +void recVUMI_ADDAz(VURegs *vuRegs, int info); +void recVUMI_ADDAw(VURegs *vuRegs, int info); +void recVUMI_SUB(VURegs *vuRegs, int info); +void recVUMI_SUBi(VURegs *vuRegs, int info); +void recVUMI_SUBq(VURegs *vuRegs, int info); +void recVUMI_SUBx(VURegs *vuRegs, int info); +void recVUMI_SUBy(VURegs *vuRegs, int info); +void recVUMI_SUBz(VURegs *vuRegs, int info); +void recVUMI_SUBw(VURegs *vuRegs, int info); +void recVUMI_SUBA(VURegs *vuRegs, int info); +void recVUMI_SUBAi(VURegs *vuRegs, int info); +void recVUMI_SUBAq(VURegs *vuRegs, int info); +void recVUMI_SUBAx(VURegs *vuRegs, int info); +void recVUMI_SUBAy(VURegs *vuRegs, int info); +void recVUMI_SUBAz(VURegs *vuRegs, int info); +void recVUMI_SUBAw(VURegs *vuRegs, int info); +void recVUMI_MUL(VURegs *vuRegs, int info); +void recVUMI_MULi(VURegs *vuRegs, int info); +void recVUMI_MULq(VURegs *vuRegs, int info); +void recVUMI_MULx(VURegs *vuRegs, int info); +void recVUMI_MULy(VURegs *vuRegs, int info); +void recVUMI_MULz(VURegs *vuRegs, int info); +void recVUMI_MULw(VURegs *vuRegs, int info); +void recVUMI_MULA(VURegs *vuRegs, int info); +void recVUMI_MULAi(VURegs *vuRegs, int info); +void recVUMI_MULAq(VURegs *vuRegs, int info); +void recVUMI_MULAx(VURegs *vuRegs, int info); +void recVUMI_MULAy(VURegs *vuRegs, int info); +void recVUMI_MULAz(VURegs *vuRegs, int info); +void recVUMI_MULAw(VURegs *vuRegs, int info); +void recVUMI_MADD(VURegs *vuRegs, int info); +void recVUMI_MADDi(VURegs *vuRegs, int info); +void recVUMI_MADDq(VURegs *vuRegs, int info); +void recVUMI_MADDx(VURegs *vuRegs, int info); +void recVUMI_MADDy(VURegs *vuRegs, int info); +void recVUMI_MADDz(VURegs *vuRegs, int info); +void recVUMI_MADDw(VURegs *vuRegs, int info); +void recVUMI_MADDA(VURegs *vuRegs, int info); +void recVUMI_MADDAi(VURegs *vuRegs, int info); +void recVUMI_MADDAq(VURegs *vuRegs, int info); +void recVUMI_MADDAx(VURegs *vuRegs, int info); +void recVUMI_MADDAy(VURegs *vuRegs, int info); +void recVUMI_MADDAz(VURegs *vuRegs, int info); +void recVUMI_MADDAw(VURegs *vuRegs, int info); +void recVUMI_MSUB(VURegs *vuRegs, int info); +void recVUMI_MSUBi(VURegs *vuRegs, int info); +void recVUMI_MSUBq(VURegs *vuRegs, int info); +void recVUMI_MSUBx(VURegs *vuRegs, int info); +void recVUMI_MSUBy(VURegs *vuRegs, int info); +void recVUMI_MSUBz(VURegs *vuRegs, int info); +void recVUMI_MSUBw(VURegs *vuRegs, int info); +void recVUMI_MSUBA(VURegs *vuRegs, int info); +void recVUMI_MSUBAi(VURegs *vuRegs, int info); +void recVUMI_MSUBAq(VURegs *vuRegs, int info); +void recVUMI_MSUBAx(VURegs *vuRegs, int info); +void recVUMI_MSUBAy(VURegs *vuRegs, int info); +void recVUMI_MSUBAz(VURegs *vuRegs, int info); +void recVUMI_MSUBAw(VURegs *vuRegs, int info); +void recVUMI_MAX(VURegs *vuRegs, int info); +void recVUMI_MAXi(VURegs *vuRegs, int info); +void recVUMI_MAXx(VURegs *vuRegs, int info); +void recVUMI_MAXy(VURegs *vuRegs, int info); +void recVUMI_MAXz(VURegs *vuRegs, int info); +void recVUMI_MAXw(VURegs *vuRegs, int info); +void recVUMI_MINI(VURegs *vuRegs, int info); +void recVUMI_MINIi(VURegs *vuRegs, int info); +void recVUMI_MINIx(VURegs *vuRegs, int info); +void recVUMI_MINIy(VURegs *vuRegs, int info); +void recVUMI_MINIz(VURegs *vuRegs, int info); +void recVUMI_MINIw(VURegs *vuRegs, int info); +void recVUMI_OPMULA(VURegs *vuRegs, int info); +void recVUMI_OPMSUB(VURegs *vuRegs, int info); +void recVUMI_NOP(VURegs *vuRegs, int info); +void recVUMI_FTOI0(VURegs *vuRegs, int info); +void recVUMI_FTOI4(VURegs *vuRegs, int info); +void recVUMI_FTOI12(VURegs *vuRegs, int info); +void recVUMI_FTOI15(VURegs *vuRegs, int info); +void recVUMI_ITOF0(VURegs *vuRegs, int info); +void recVUMI_ITOF4(VURegs *vuRegs, int info); +void recVUMI_ITOF12(VURegs *vuRegs, int info); +void recVUMI_ITOF15(VURegs *vuRegs, int info); +void recVUMI_CLIP(VURegs *vuRegs, int info); + +/***************************************** + VU Micromode Lower instructions +*****************************************/ + +void recVUMI_DIV(VURegs *vuRegs, int info); +void recVUMI_SQRT(VURegs *vuRegs, int info); +void recVUMI_RSQRT(VURegs *vuRegs, int info); +void recVUMI_IADD(VURegs *vuRegs, int info); +void recVUMI_IADDI(VURegs *vuRegs, int info); +void recVUMI_IADDIU(VURegs *vuRegs, int info); +void recVUMI_IAND(VURegs *vuRegs, int info); +void recVUMI_IOR(VURegs *vuRegs, int info); +void recVUMI_ISUB(VURegs *vuRegs, int info); +void recVUMI_ISUBIU(VURegs *vuRegs, int info); +void recVUMI_MOVE(VURegs *vuRegs, int info); +void recVUMI_MFIR(VURegs *vuRegs, int info); +void recVUMI_MTIR(VURegs *vuRegs, int info); +void recVUMI_MR32(VURegs *vuRegs, int info); +void recVUMI_LQ(VURegs *vuRegs, int info); +void recVUMI_LQD(VURegs *vuRegs, int info); +void recVUMI_LQI(VURegs *vuRegs, int info); +void recVUMI_SQ(VURegs *vuRegs, int info); +void recVUMI_SQD(VURegs *vuRegs, int info); +void recVUMI_SQI(VURegs *vuRegs, int info); +void recVUMI_ILW(VURegs *vuRegs, int info); +void recVUMI_ISW(VURegs *vuRegs, int info); +void recVUMI_ILWR(VURegs *vuRegs, int info); +void recVUMI_ISWR(VURegs *vuRegs, int info); +void recVUMI_LOI(VURegs *vuRegs, int info); +void recVUMI_RINIT(VURegs *vuRegs, int info); +void recVUMI_RGET(VURegs *vuRegs, int info); +void recVUMI_RNEXT(VURegs *vuRegs, int info); +void recVUMI_RXOR(VURegs *vuRegs, int info); +void recVUMI_WAITQ(VURegs *vuRegs, int info); +void recVUMI_FSAND(VURegs *vuRegs, int info); +void recVUMI_FSEQ(VURegs *vuRegs, int info); +void recVUMI_FSOR(VURegs *vuRegs, int info); +void recVUMI_FSSET(VURegs *vuRegs, int info); +void recVUMI_FMAND(VURegs *vuRegs, int info); +void recVUMI_FMEQ(VURegs *vuRegs, int info); +void recVUMI_FMOR(VURegs *vuRegs, int info); +void recVUMI_FCAND(VURegs *vuRegs, int info); +void recVUMI_FCEQ(VURegs *vuRegs, int info); +void recVUMI_FCOR(VURegs *vuRegs, int info); +void recVUMI_FCSET(VURegs *vuRegs, int info); +void recVUMI_FCGET(VURegs *vuRegs, int info); +void recVUMI_IBEQ(VURegs *vuRegs, int info); +void recVUMI_IBGEZ(VURegs *vuRegs, int info); +void recVUMI_IBGTZ(VURegs *vuRegs, int info); +void recVUMI_IBLTZ(VURegs *vuRegs, int info); +void recVUMI_IBLEZ(VURegs *vuRegs, int info); +void recVUMI_IBNE(VURegs *vuRegs, int info); +void recVUMI_B(VURegs *vuRegs, int info); +void recVUMI_BAL(VURegs *vuRegs, int info); +void recVUMI_JR(VURegs *vuRegs, int info); +void recVUMI_JALR(VURegs *vuRegs, int info); +void recVUMI_MFP(VURegs *vuRegs, int info); +void recVUMI_WAITP(VURegs *vuRegs, int info); +void recVUMI_ESADD(VURegs *vuRegs, int info); +void recVUMI_ERSADD(VURegs *vuRegs, int info); +void recVUMI_ELENG(VURegs *vuRegs, int info); +void recVUMI_ERLENG(VURegs *vuRegs, int info); +void recVUMI_EATANxy(VURegs *vuRegs, int info); +void recVUMI_EATANxz(VURegs *vuRegs, int info); +void recVUMI_ESUM(VURegs *vuRegs, int info); +void recVUMI_ERCPR(VURegs *vuRegs, int info); +void recVUMI_ESQRT(VURegs *vuRegs, int info); +void recVUMI_ERSQRT(VURegs *vuRegs, int info); +void recVUMI_ESIN(VURegs *vuRegs, int info); +void recVUMI_EATAN(VURegs *vuRegs, int info); +void recVUMI_EEXP(VURegs *vuRegs, int info); +void recVUMI_XGKICK(VURegs *vuRegs, int info); +void recVUMI_XTOP(VURegs *vuRegs, int info); +void recVUMI_XITOP(VURegs *vuRegs, int info); +void recVUMI_XTOP( VURegs *VU , int info); + +#endif /* __IVUMICRO_H__ */ diff --git a/x86/iVUops.h b/x86/iVUops.h new file mode 100644 index 0000000000..79d4a78b8d --- /dev/null +++ b/x86/iVUops.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define REC_VUOP(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUOPFLAGS(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUBRANCH(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(&VU0); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + MOV32ItoM((u32)&VU.VI[REG_TPC].UL, (u32)pc); \ + CALLFunc((u32)VU##MI_##f); \ + branch = 1; \ +} \ No newline at end of file diff --git a/x86/iVUzerorec.cpp b/x86/iVUzerorec.cpp new file mode 100644 index 0000000000..dcade661a6 --- /dev/null +++ b/x86/iVUzerorec.cpp @@ -0,0 +1,3639 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Common.h" +#include "ix86/ix86.h" +#include "ir5900.h" +#include "iMMI.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +// temporary externs +extern u32 vudump; +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); + +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include +using namespace std; + +#ifdef __MSCW32__ + +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// SuperVURec options +#define SUPERVU_CACHING // vu programs are saved and queried via CRC (might query the wrong program) + // disable when in doubt +#define SUPERVU_X86CACHING // use x86reg caching (faster) +#define SUPERVU_INTERCACHING // registers won't be flushed at block boundaries (faster) + +#define VU_EXESIZE 0x00800000 + +#define _Imm11_ ((s32)(vucode & 0x400 ? 0xfffffc00 | (vucode & 0x3ff) : vucode & 0x3ff)&0x3fff) +#define _UImm11_ ((s32)(vucode & 0x7ff)&0x3fff) + +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +static const u32 QWaitTimes[] = { 6, 12 }; +static const u32 PWaitTimes[] = { 53, 43, 28, 23, 17, 11, 10 }; + +static u32 s_vuInfo; // info passed into rec insts + +static const u32 s_MemSize[2] = {VU0_MEMSIZE, VU1_MEMSIZE}; +static char* s_recVUMem = NULL, *s_recVUPtr = NULL; + +// tables +extern void (*recSVU_UPPER_OPCODE[64])(); +extern void (*recSVU_LOWER_OPCODE[128])(); + +#define INST_Q_READ 0x0001 // flush Q +#define INST_P_READ 0x0002 // flush P +#define INST_BRANCH_DELAY 0x0004 +#define INST_CLIP_WRITE 0x0040 // inst writes CLIP in the future +#define INST_STATUS_WRITE 0x0080 +#define INST_MAC_WRITE 0x0100 +#define INST_Q_WRITE 0x0200 +#define INST_DUMMY_ 0x8000 +#define INST_DUMMY 0x83c0 + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +union VURecRegs +{ + struct { + u16 reg; + u16 type; + }; + u32 id; +}; + +class VuBaseBlock; + +struct VuFunctionHeader +{ + struct RANGE + { + u16 start, size; + u32 checksum[2]; // xor of all the code + }; + + VuFunctionHeader() : pprogfunc(NULL), startpc(0xffffffff) {} + + // returns true if the checksum for the current mem is the same as this fn + bool IsSame(void* pmem); + + u32 startpc; + void* pprogfunc; + + vector ranges; +}; + +struct VuBlockHeader +{ + VuBaseBlock* pblock; + u32 delay; +}; + +// one vu inst (lower and upper) +class VuInstruction +{ +public: + VuInstruction() { memset(this, 0, sizeof(VuInstruction)); nParentPc = -1; } + + int nParentPc; // used for syncing with flag writes, -1 for no parent + + _vuopinfo info; + + _VURegsNum regs[2]; // [0] - lower, [1] - upper + u32 livevars[2]; // live variables right before this inst, [0] - inst, [1] - float + u32 addvars[2]; // live variables to add + u32 usedvars[2]; // set if var is used in the future including vars used in this inst + u32 keepvars[2]; + u16 pqcycles; // the number of cycles to stall if function writes to the regs + u16 type; // INST_ + + u32 pClipWrite, pMACWrite, pStatusWrite; // addrs to write the flags + u32 vffree[2]; + s8 vfwrite[2], vfread0[2], vfread1[2], vfacc[2]; + s8 vfflush[2]; // extra flush regs + + int SetCachedRegs(int upper, u32 vuxyz); + void Recompile(list::const_iterator& itinst, u32 vuxyz); +}; + +#define BLOCKTYPE_EOP 0x01 // at least one of the children of the block contains eop (or the block itself) +#define BLOCKTYPE_FUNCTION 0x02 +#define BLOCKTYPE_HASEOP 0x04 // last inst of block is an eop +#define BLOCKTYPE_MACFLAGS 0x08 +#define BLOCKTYPE_ANALYZED 0x40 +#define BLOCKTYPE_IGNORE 0x80 // special for recursive fns +#define BLOCKTYPE_ANALYZEDPARENT 0x100 + +// base block used when recompiling +class VuBaseBlock +{ +public: + typedef list LISTBLOCKS; + + VuBaseBlock(); + + // returns true if the leads to a EOP (ALL VU blocks must ret true) + void AssignVFRegs(); + void AssignVIRegs(int parent); + + // returns true if only xyz of the reg has been used so far + u32 GetModeXYZW(u32 curpc, int vfreg); + + list::iterator GetInstIterAtPc(int instpc) + { + assert( instpc >= 0 ); + + u32 curpc = startpc; + list::iterator it; + for(it = insts.begin(); it != insts.end(); ++it) { + if( it->type & INST_DUMMY ) + continue; + + if( curpc == instpc ) + break; + curpc += 8; + } + + assert( it != insts.end() ); + return it; + } + + VuInstruction* GetInstAtPc(int instpc) { return &(*GetInstIterAtPc(instpc)); } + + void Recompile(); + + u16 type; // BLOCKTYPE_ + u16 id; + u16 startpc; + u16 endpc; // first inst not in block + void* pcode; // x86 code pointer + int cycles; + list insts; + list parents; + LISTBLOCKS blocks; // blocks branches to + u32* pChildJumps[4]; // addrs that need to be filled with the children's start addrs + // if highest bit is set, addr needs to be relational + u32 vuxyz; // corresponding bit is set if reg's xyz channels are used only + u32 vuxy; // corresponding bit is set if reg's xyz channels are used only + + _xmmregs startregs[XMMREGS], endregs[XMMREGS]; + int nStartx86, nEndx86; // indices into s_vecRegArray + + int allocX86Regs; +}; + +VuBaseBlock::VuBaseBlock() +{ + type = 0; endpc = 0; cycles = 0; pcode = NULL; id = 0; + memset(pChildJumps, 0, sizeof(pChildJumps)); + memset(startregs, 0, sizeof(startregs)); + memset(endregs, 0, sizeof(endregs)); + allocX86Regs = nStartx86 = nEndx86 = -1; +} + +#define SUPERVU_STACKSIZE 0x1000 + +static list s_listVUHeaders[2]; +static list* s_plistCachedHeaders[2]; +static VuFunctionHeader** recVUHeaders[2] = {NULL}; +static VuBlockHeader* recVUBlocks[2] = {NULL}; +static u8* recVUStack = NULL, *recVUStackPtr = NULL; +static vector<_x86regs> s_vecRegArray(128); + +static VURegs* VU = NULL; +static list s_listBlocks; +static u32 s_vu = 0; + +// Global functions +static void* SuperVUGetProgram(u32 startpc, int vuindex); +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex); +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc); +static void SuperVUInitLiveness(VuBaseBlock* pblock); +static void SuperVULivenessAnalysis(); +static void SuperVUEliminateDeadCode(); +static void SuperVUAssignRegs(); + +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg); +#define SuperVUFreeXMMreg 0&& +void SuperVUFreeXMMregs(u32* livevars); + +static u32* SuperVUStaticAlloc(u32 size); +static void SuperVURecompile(); + +// allocate VU resources +void SuperVUInit(int vuindex) +{ + if( vuindex < 0 ) { + s_recVUMem = (char*)SysMmap(0, VU_EXESIZE); + memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + recVUStack = new u8[SUPERVU_STACKSIZE * 4]; + } + else { + recVUHeaders[vuindex] = new VuFunctionHeader* [s_MemSize[vuindex]/8]; + recVUBlocks[vuindex] = new VuBlockHeader[s_MemSize[vuindex]/8]; + s_plistCachedHeaders[vuindex] = new list[s_MemSize[vuindex]/8]; + } +} + +// destroy VU resources +void SuperVUDestroy(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUDestroy(0); + SuperVUDestroy(1); + SysMunmap((uptr)s_recVUMem, VU_EXESIZE); + s_recVUPtr = NULL; + delete[] recVUStack; recVUStack = NULL; + } + else { + delete[] recVUHeaders[vuindex]; recVUHeaders[vuindex] = NULL; + delete[] recVUBlocks[vuindex]; recVUBlocks[vuindex] = NULL; + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + delete[] s_plistCachedHeaders[vuindex]; s_plistCachedHeaders[vuindex] = NULL; + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// reset VU +void SuperVUReset(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUReset(0); + SuperVUReset(1); + + //memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + + memset(recVUStack, 0, SUPERVU_STACKSIZE); + } + else { + if( recVUHeaders[vuindex] ) memset( recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex]/8) ); + if( recVUBlocks[vuindex] ) memset( recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex]/8) ); + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// clear the block and any joining blocks +void SuperVUClear(u32 startpc, u32 size, int vuindex) +{ + vector::iterator itrange; + list::iterator it = s_listVUHeaders[vuindex].begin(); + u32 endpc = startpc+size; + while( it != s_listVUHeaders[vuindex].end() ) { + + // for every fn, check if it has code in the range + FORIT(itrange, (*it)->ranges) { + if( startpc < (u32)itrange->start+itrange->size && itrange->start < endpc ) + break; + } + + if( itrange != (*it)->ranges.end() ) { + recVUHeaders[vuindex][(*it)->startpc/8] = NULL; +#ifdef SUPERVU_CACHING + list* plist = &s_plistCachedHeaders[vuindex][(*it)->startpc/8]; + plist->push_back(*it); + if( plist->size() > 10 ) { + // list is too big, delete + delete plist->front(); + plist->pop_front(); + } + it = s_listVUHeaders[vuindex].erase(it); +#else + delete *it; + it = s_listVUHeaders[vuindex].erase(it); +#endif + } + else ++it; + } +} + +static VuFunctionHeader* s_pFnHeader = NULL; +static VuBaseBlock* s_pCurBlock = NULL; +static VuInstruction* s_pCurInst = NULL; +static u32 s_StatusRead = 0, s_MACRead = 0, s_ClipRead = 0; // read addrs +static u32 s_PrevStatusWrite = 0, s_PrevClipWrite = 0, s_PrevIWrite = 0; +static u32 s_WriteToReadQ = 0; + +int SuperVUGetLiveness(int vfreg) +{ + assert( s_pCurInst != NULL ); + if( vfreg == 32 ) return ((s_pCurInst->livevars[0]&(1<usedvars[0]&(1<livevars[0]&(1<usedvars[0]&(1<livevars[1]&(1<usedvars[1]&(1<pStatusWrite); + assert(!read || addr != 0); + return addr; + } + case REG_MAC_FLAG: + { + return read ? s_MACRead : s_pCurInst->pMACWrite; + } + case REG_CLIP_FLAG: + { + u32 addr = (read==2) ? s_PrevClipWrite : (read ? s_ClipRead : s_pCurInst->pClipWrite); + assert( !read || addr != 0 ); + return addr; + } + case REG_Q: return (read || s_WriteToReadQ) ? (int)&VU->VI[REG_Q] : (u32)(u32)&VU->q; + case REG_P: return read ? (int)&VU->VI[REG_P] : (u32)(u32)&VU->p; + case REG_I: return s_PrevIWrite; + } + + return (u32)&VU->VI[reg]; +} + +void SuperVUDumpBlock(list& blocks, int vuindex) +{ + FILE *f; + char filename[ 256 ], str[256]; + u32 *mem; + u32 i; + static int gid = 0; + +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#endif + //SysPrintf( "dump1 %x => %s\n", s_pFnHeader->startpc, filename ); + + f = fopen( filename, "w" ); + + fprintf(f, "Format: upper_inst lower_inst\ntype f:vf_live_vars vf_used_vars i:vi_live_vars vi_used_vars inst_cycle pq_inst\n"); + fprintf(f, "Type: %.2x - qread, %.2x - pread, %.2x - clip_write, %.2x - status_write\n" + "%.2x - mac_write, %.2x -qflush\n", + INST_Q_READ, INST_P_READ, INST_CLIP_WRITE, INST_STATUS_WRITE, INST_MAC_WRITE, INST_Q_WRITE); + fprintf(f, "XMM: Upper: read0 read1 write acc temp; Lower: read0 read1 write acc temp\n\n"); + + list::iterator itblock; + list::iterator itinst; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + FORIT(itblock, blocks) { + fprintf(f, "block:%c %x-%x; children: ", ((*itblock)->type&BLOCKTYPE_HASEOP)?'*':' ', + (*itblock)->startpc, (*itblock)->endpc-8); + FORIT(itchild, (*itblock)->blocks) { + fprintf(f, "%x ", (*itchild)->startpc); + } + fprintf(f, "; vuxyz = %x, vuxy = %x\n", (*itblock)->vuxyz&(*itblock)->insts.front().usedvars[1], + (*itblock)->vuxy&(*itblock)->insts.front().usedvars[1]); + + itinst = (*itblock)->insts.begin(); + i = (*itblock)->startpc; + while(itinst != (*itblock)->insts.end() ) { + assert( i <= (*itblock)->endpc ); + if( itinst->type & INST_DUMMY ) { + if( itinst->nParentPc >= 0 && !(itinst->type&INST_DUMMY_)) { + // search for the parent + VuInstruction* p = (*itblock)->GetInstAtPc(itinst->nParentPc); + fprintf(f, "writeback 0x%x (%x)\n", itinst->type, itinst->nParentPc); + } + } + else { + mem = (u32*)&VU->Micro[i]; + char* pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%.4x: %-40s", i, pstr); + if( mem[1] & 0x80000000 ) fprintf(f, " I=%f(%.8x)\n", *(float*)mem, mem[0]); + else fprintf(f, "%s\n", disVU1MicroLF( mem[0], i )); + i += 8; + } + + ++itinst; + } + + fprintf(f, "\n"); + + _x86regs* pregs; + if( (*itblock)->nStartx86 >= 0 || (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "X86: AX CX DX BX SP BP SI DI\n"); + } + + if( (*itblock)->nStartx86 >= 0 ) { + pregs = &s_vecRegArray[(*itblock)->nStartx86]; + fprintf(f, "STR: "); + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + if( (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "END: "); + pregs = &s_vecRegArray[(*itblock)->nEndx86]; + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + itinst = (*itblock)->insts.begin(); + for ( i = (*itblock)->startpc; i < (*itblock)->endpc; ++itinst ) { + + if( itinst->type & INST_DUMMY ) { + } + else { + sprintf(str, "%.4x:%x f:%.8x_%.8x", i, itinst->type, itinst->livevars[1], itinst->usedvars[1]); + fprintf(f, "%-46s i:%.8x_%.8x c:%d pq:%d\n", str, + itinst->livevars[0], itinst->usedvars[0], (int)itinst->info.cycle, (int)itinst->pqcycles ); + + sprintf(str, "XMM r0:%d r1:%d w:%d a:%d t:%x;", + itinst->vfread0[1], itinst->vfread1[1], itinst->vfwrite[1], itinst->vfacc[1], itinst->vffree[1]); + fprintf(f, "%-46s r0:%d r1:%d w:%d a:%d t:%x\n", str, + itinst->vfread0[0], itinst->vfread1[0], itinst->vfwrite[0], itinst->vfacc[0], itinst->vffree[0]); + i += 8; + } + } + + fprintf(f, "\n---------------\n"); + } + + fclose( f ); +} + +static LARGE_INTEGER svubase, svufinal; +static u32 svutime; + +// uncomment to count svu exec time +//#define SUPERVU_COUNT +u32 SuperVUGetRecTimes(int clear) +{ + u32 temp = svutime; + if( clear ) svutime = 0; + return temp; +} + +// Private methods +static void* SuperVUGetProgram(u32 startpc, int vuindex) +{ + assert( startpc < s_MemSize[vuindex] ); + assert( (startpc%8) == 0 ); + assert( recVUHeaders[vuindex] != NULL ); + VuFunctionHeader** pheader = &recVUHeaders[vuindex][startpc/8]; + + if( *pheader == NULL ) { +#ifdef _DEBUG +// if( vuindex ) VU1.VI[REG_TPC].UL = startpc; +// else VU0.VI[REG_TPC].UL = startpc; +// __Log("VU: %x\n", startpc); +// iDumpVU1Registers(); +// vudump |= 2; +#endif + + // measure run time + //QueryPerformanceCounter(&svubase); + +#ifdef SUPERVU_CACHING + void* pmem = (vuindex&1) ? VU1.Micro : VU0.Micro; + // check if program exists in cache + list::iterator it; + FORIT(it, s_plistCachedHeaders[vuindex][startpc/8]) { + if( (*it)->IsSame(pmem) ) { + // found, transfer to regular lists + void* pfn = (*it)->pprogfunc; + recVUHeaders[vuindex][startpc/8] = *it; + s_listVUHeaders[vuindex].push_back(*it); + s_plistCachedHeaders[vuindex][startpc/8].erase(it); + return pfn; + } + } +#endif + + *pheader = SuperVURecompileProgram(startpc, vuindex); + + //QueryPerformanceCounter(&svufinal); + //svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); + + assert( (*pheader)->pprogfunc != NULL ); + } + + assert( (*pheader)->startpc == startpc ); + + return (*pheader)->pprogfunc; +} + +bool VuFunctionHeader::IsSame(void* pmem) +{ +#ifdef SUPERVU_CACHING + u32 checksum[2]; + vector::iterator it; + FORIT(it, ranges) { + memxor_mmx(checksum, (u8*)pmem+it->start, it->size); + if( checksum[0] != it->checksum[0] || checksum[1] != it->checksum[1] ) + return false; + } +#endif + return true; +} + +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex) +{ + assert( vuindex < 2 ); + assert( s_recVUPtr != NULL ); + //SysPrintf("svu%c rec: %x\n", '0'+vuindex, startpc); + + // if recPtr reached the mem limit reset whole mem + if ( ( (u32)s_recVUPtr - (u32)s_recVUMem ) >= VU_EXESIZE-0x40000 ) { + //SysPrintf("SuperVU reset mem\n"); + SuperVUReset(-1); + } + + list::iterator itblock; + + s_vu = vuindex; + VU = s_vu ? &VU1 : &VU0; + s_pFnHeader = new VuFunctionHeader(); + s_listVUHeaders[vuindex].push_back(s_pFnHeader); + s_pFnHeader->startpc = startpc; + + memset( recVUBlocks[s_vu], 0, sizeof(VuBlockHeader) * (s_MemSize[s_vu]/8) ); + + // analyze the global graph + s_listBlocks.clear(); + SuperVUBuildBlocks(NULL, startpc); + + // fill parents + VuBaseBlock::LISTBLOCKS::iterator itchild; + FORIT(itblock, s_listBlocks) { + FORIT(itchild, (*itblock)->blocks) + (*itchild)->parents.push_back(*itblock); + + //(*itblock)->type &= ~(BLOCKTYPE_IGNORE|BLOCKTYPE_ANALYZED); + } + + assert( s_listBlocks.front()->startpc == startpc ); + s_listBlocks.front()->type |= BLOCKTYPE_FUNCTION; + + FORIT(itblock, s_listBlocks) { + SuperVUInitLiveness(*itblock); + } + + SuperVULivenessAnalysis(); + SuperVUEliminateDeadCode(); + SuperVUAssignRegs(); + +#ifdef _DEBUG + if( (s_vu && (vudump&1)) || (!s_vu && (vudump&16)) ) + SuperVUDumpBlock(s_listBlocks, s_vu); +#endif + + // code generation + x86SetPtr(s_recVUPtr); + _initXMMregs(); + branch = 0; + + SuperVURecompile(); + + s_recVUPtr = x86Ptr; + + // set the function's range + VuFunctionHeader::RANGE r; + s_pFnHeader->ranges.reserve(s_listBlocks.size()); + + FORIT(itblock, s_listBlocks) { + r.start = (*itblock)->startpc; + r.size = (*itblock)->endpc-(*itblock)->startpc; +#ifdef SUPERVU_CACHING + memxor_mmx(r.checksum, &VU->Micro[r.start], r.size); +#endif + s_pFnHeader->ranges.push_back(r); + } + + // destroy + for(list::iterator itblock = s_listBlocks.begin(); itblock != s_listBlocks.end(); ++itblock) { + delete *itblock; + } + s_listBlocks.clear(); + + assert( s_recVUPtr < s_recVUMem+VU_EXESIZE ); + + return s_pFnHeader; +} + +static int _recbranchAddr(u32 vucode) { + u32 bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + bpc &= (s_MemSize[s_vu]-1); + + return bpc; +} + +struct WRITEBACK +{ + void InitInst(VuInstruction* pinst, int cycle) + { + u32 write = viwrite[0]|viwrite[1]; + pinst->type = ((write&(1<nParentPc = nParentPc; + pinst->info.cycle = cycle; + for(int i = 0; i < 2; ++i) { + pinst->regs[i].VIwrite = viwrite[i]; + pinst->regs[i].VIread = viread[i]; + } + } + + static int SortWritebacks(const WRITEBACK& w1, const WRITEBACK& w2) { + return w1.cycle < w2.cycle; + } + + int nParentPc; + int cycle; + u32 viwrite[2]; + u32 viread[2]; +}; + +// return inst that flushes everything +static VuInstruction SuperVUFlushInst() +{ + VuInstruction inst; + // don't need to raed q/p + inst.type = INST_DUMMY_;//|INST_Q_READ|INST_P_READ; + return inst; +} + +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc) +{ + // check if block already exists + VuBlockHeader* pbh = &recVUBlocks[s_vu][startpc/8]; + if( pbh->pblock != NULL ) { + VuBaseBlock* pblock = pbh->pblock; + if( pblock->startpc == startpc ) + return pblock; + + // have to divide the blocks, pnewblock is first block + assert( startpc > pblock->startpc ); + assert( startpc < pblock->endpc ); + + u32 dummyinst = (startpc-pblock->startpc)>>3; + + // count inst non-dummy insts + list::iterator itinst = pblock->insts.begin(); + u32 inst = 0; + while(dummyinst > 0) { + if( itinst->type & INST_DUMMY ) + ++itinst; + else { + ++itinst; + --dummyinst; + } + } + + // NOTE: still leaves insts with their writebacks in different blocks + while( itinst->type & INST_DUMMY ) + ++itinst; + + int cycleoff = itinst->info.cycle; + + // new block + VuBaseBlock* pnewblock = new VuBaseBlock(); + s_listBlocks.push_back(pnewblock); + + pnewblock->startpc = startpc; + pnewblock->endpc = pblock->endpc; + pnewblock->cycles = pblock->cycles-cycleoff; + + pnewblock->blocks.splice(pnewblock->blocks.end(), pblock->blocks); + pnewblock->insts.splice(pnewblock->insts.end(), pblock->insts, itinst, pblock->insts.end()); + pnewblock->type = pblock->type; + + // any writebacks in the next 3 cycles also belong to original block + for(itinst = pnewblock->insts.begin(); itinst != pnewblock->insts.end(); ) { + if( (itinst->type & INST_DUMMY) && itinst->nParentPc >= 0 && itinst->nParentPc < (int)startpc ) { + + if( !(itinst->type & INST_Q_WRITE) ) + pblock->insts.push_back(*itinst); + itinst = pnewblock->insts.erase(itinst); + continue; + } + + ++itinst; + } + + pbh = &recVUBlocks[s_vu][startpc/8]; + for(u32 inst = startpc; inst < pblock->endpc; inst += 8) { + if( pbh->pblock == pblock ) + pbh->pblock = pnewblock; + ++pbh; + } + + FORIT(itinst, pnewblock->insts) + itinst->info.cycle -= cycleoff; + + // old block + pblock->blocks.push_back(pnewblock); + pblock->endpc = startpc; + pblock->cycles = cycleoff; + pblock->type &= BLOCKTYPE_MACFLAGS;; + //pblock->insts.push_back(SuperVUFlushInst()); //don't need + + return pnewblock; + } + + VuBaseBlock* pblock = new VuBaseBlock(); + s_listBlocks.push_back(pblock); + + int i = 0; + branch = 0; + pc = startpc; + pblock->startpc = startpc; + + // clear stalls (might be a prob) + memset(VU->fmac,0,sizeof(VU->fmac)); + memset(&VU->fdiv,0,sizeof(VU->fdiv)); + memset(&VU->efu,0,sizeof(VU->efu)); + vucycle = 0; + + u8 macflags = 0; + + list< WRITEBACK > listWritebacks; + list< WRITEBACK >::iterator itwriteback; + list::iterator itinst; + u32 hasSecondBranch = 0; + u32 needFullStatusFlag = 0; + + // first analysis pass for status flags + while(1) { + u32* ptr = (u32*)&VU->Micro[pc]; + pc += 8; + int prevbranch = branch; + + if( ptr[1] & 0x40000000 ) + branch = 1; + + if( !(ptr[1] & 0x80000000) ) { // not I + switch( ptr[0]>>25 ) { + case 0x24: // jr + case 0x25: // jalr + case 0x20: // B + case 0x21: // BAL + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + branch = 1; + break; + + case 0x14: // fseq + case 0x17: // fsor + //needFullStatusFlag = 2; + break; + + case 0x16: // fsand + if( (ptr[0]&0xc0) ) { + // sometimes full sticky bits are needed (simple series 2000 - oane chapara) + //SysPrintf("needSticky: %x-%x\n", s_pFnHeader->startpc, startpc); + needFullStatusFlag = 2; + } + break; + } + } + + if( prevbranch ) + break; + + assert( pc < s_MemSize[s_vu] ); + } + + // second full pass + pc = startpc; + branch = 0; + + while(1) { + + if( !branch && pbh->pblock != NULL ) { + pblock->blocks.push_back(pbh->pblock); + break; + } + + int prevbranch = branch; + + if( !prevbranch ) { + pbh->pblock = pblock; + } + else assert( prevbranch || pbh->pblock == NULL); + + pblock->insts.push_back(VuInstruction()); + + VuInstruction* pinst = &pblock->insts.back(); + SuperVUAnalyzeOp(VU, &pinst->info, pinst->regs); + + if( prevbranch ) { + if( pinst->regs[0].pipe == VUPIPE_BRANCH ) + hasSecondBranch = 1; + pinst->type |= INST_BRANCH_DELAY; + } + + // check write back + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ) { + if( pinst->info.cycle >= itwriteback->cycle ) { + itinst = pblock->insts.insert(--pblock->insts.end(), VuInstruction()); + itwriteback->InitInst(&(*itinst), pinst->info.cycle); + itwriteback = listWritebacks.erase(itwriteback); + } + else ++itwriteback; + } + + // add new writebacks + WRITEBACK w = {0}; + const u32 allflags = (1<regs[j].VIwrite & allflags; + + if( pinst->info.macflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.statusflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.macflag|pinst->info.statusflag) & VUOP_READ ) + macflags = 1; + if( pinst->regs[0].VIread & ((1<VIwrite |= lregs->VIwrite & (1<info.statusflag&VUOP_WRITE)&&!(pinst->regs[0].VIwrite&(1<regs[j].VIread & allflags; + + if( (pinst->regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIwrite &= ~allflags; + } + + if( pinst->info.macflag & VUOP_READ) w.viread[1] |= 1<info.statusflag & VUOP_READ) w.viread[1] |= 1<info.cycle+4; + listWritebacks.push_back(w); + } + + if( pinst->info.q&VUOP_READ ) pinst->type |= INST_Q_READ; + if( pinst->info.p&VUOP_READ ) pinst->type |= INST_P_READ; + + if( pinst->info.q&VUOP_WRITE ) { + pinst->pqcycles = QWaitTimes[pinst->info.pqinst]; + + memset(&w, 0, sizeof(w)); + w.nParentPc = pc-8; + w.cycle = pinst->info.cycle+pinst->pqcycles+1; + w.viwrite[0] = 1<info.p&VUOP_WRITE ) + pinst->pqcycles = PWaitTimes[pinst->info.pqinst]; + + if( prevbranch ) + break; + + // make sure there is always a branch + if( (s_vu==1 && i >= 0x798) || (s_vu==0 && i >= 0x198) ) { + SysPrintf("VuRec base block doesn't terminate!\n"); + break; + } + + i++; + pbh++; + } + + if( listWritebacks.size() > 0 ) { + listWritebacks.sort(WRITEBACK::SortWritebacks); + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ++itwriteback) { + if( itwriteback->viwrite[0] & (1<insts.push_back(VuInstruction()); + itwriteback->InitInst(&pblock->insts.back(), vucycle); + } + } + + if( macflags ) + pblock->type |= BLOCKTYPE_MACFLAGS; + + u32 lastpc = pc; + pblock->endpc = lastpc; + + pblock->cycles = vucycle; + + if( !branch ) + return pblock; + + if( branch & 8 ) { + // what if also a jump? + pblock->type |= BLOCKTYPE_EOP|BLOCKTYPE_HASEOP; + + // add an instruction to flush p and q (if written) + pblock->insts.push_back(SuperVUFlushInst()); + return pblock; + } + + // it is a (cond) branch or a jump + u32 vucode = *(u32*)(VU->Micro+lastpc-16); + int bpc = _recbranchAddr(vucode)-8; + + switch(vucode>>25) { + case 0x24: // jr + pblock->type |= BLOCKTYPE_EOP; // jump out of procedure, since not returning, set EOP + pblock->insts.push_back(SuperVUFlushInst()); + break; + + case 0x25: // jalr + { + // linking, so will return to procedure + pblock->insts.push_back(SuperVUFlushInst()); + + VuBaseBlock* pjumpblock = SuperVUBuildBlocks(pblock, lastpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pjumpblock); + break; + } + case 0x20: // B + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + pbranchblock = SuperVUBuildBlocks(pblock, lastpc); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + break; + } + default: + assert(pblock->blocks.size() == 1); + break; + } + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + if( hasSecondBranch ) { + u32 vucode = *(u32*)(VU->Micro+lastpc-8); + pc = lastpc; + int bpc = _recbranchAddr(vucode); + + switch(vucode>>25) { + case 0x24: // jr + SysPrintf("svurec bad jr jump!\n"); + assert(0); + break; + + case 0x25: // jalr + { + SysPrintf("svurec bad jalr jump!\n"); + assert(0); + break; + } + case 0x20: // B + { + assert(0); + pblock->blocks.clear(); + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + assert(0); + pblock->blocks.clear(); + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + pbranchblock = SuperVUBuildBlocks(pblock, lastpc+8); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + break; + } + default: + assert(0); + } + } + + return recVUBlocks[s_vu][startpc/8].pblock; +} + +static void SuperVUInitLiveness(VuBaseBlock* pblock) +{ + list::iterator itinst, itnext; + + assert( pblock->insts.size() > 0 ); + + for(itinst = pblock->insts.begin(); itinst != pblock->insts.end(); ++itinst) { + + if( itinst->type & INST_DUMMY_ ) { + itinst->addvars[0] = itinst->addvars[1] = 0xffffffff; + itinst->livevars[0] = itinst->livevars[1] = 0xffffffff; + itinst->keepvars[0] = itinst->keepvars[1] = 0xffffffff; + itinst->usedvars[0] = itinst->usedvars[1] = 0; + } + else { + itinst->addvars[0] = itinst->regs[0].VIread | itinst->regs[1].VIread; + itinst->addvars[1] = (itinst->regs[0].VFread0 ? (1 << itinst->regs[0].VFread0) : 0) | + (itinst->regs[0].VFread1 ? (1 << itinst->regs[0].VFread1) : 0) | + (itinst->regs[1].VFread0 ? (1 << itinst->regs[1].VFread0) : 0) | + (itinst->regs[1].VFread1 ? (1 << itinst->regs[1].VFread1) : 0); + + // vf0 is not handled by VFread + if( !itinst->regs[0].VFread0 && (itinst->regs[0].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[1].VFread0 && (itinst->regs[1].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[0].VFread1 && (itinst->regs[0].VIread & (1<regs[0].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + if( !itinst->regs[1].VFread1 && (itinst->regs[1].VIread & (1<regs[1].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + + + u32 vfwrite = 0; + if( itinst->regs[0].VFwrite != 0 ) { + if( itinst->regs[0].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[0].VFwrite; + else vfwrite |= 1<regs[0].VFwrite; + } + if( itinst->regs[1].VFwrite != 0 ) { + if( itinst->regs[1].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[1].VFwrite; + else vfwrite |= 1<regs[1].VFwrite; + } + if( (itinst->regs[1].VIwrite & (1<regs[1].VFwxyzw != 0xf ) + itinst->addvars[1] |= 1<regs[0].VIwrite|itinst->regs[1].VIwrite); + + itinst->usedvars[0] = itinst->addvars[0]|viwrite; + itinst->usedvars[1] = itinst->addvars[1]|vfwrite; + +// itinst->addvars[0] &= ~viwrite; +// itinst->addvars[1] &= ~vfwrite; + itinst->keepvars[0] = ~viwrite; + itinst->keepvars[1] = ~vfwrite; + } + } + + itinst = --pblock->insts.end(); + while( itinst != pblock->insts.begin() ) { + itnext = itinst; --itnext; + + itnext->usedvars[0] |= itinst->usedvars[0]; + itnext->usedvars[1] |= itinst->usedvars[1]; + + itinst = itnext; + } +} + +u32 COMPUTE_LIVE(u32 R, u32 K, u32 L) +{ + u32 live = R | ((L)&(K)); + // speciall process mac and status flags + // only propagate liveness if doesn't write to the flag + if( !(L&(1<::reverse_iterator itblock; + list::iterator itinst, itnext; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + u32 livevars[2]; + + do { + changed = FALSE; + for(itblock = s_listBlocks.rbegin(); itblock != s_listBlocks.rend(); ++itblock) { + + u32 newlive; + VuBaseBlock* pb = *itblock; + + // the last inst relies on the neighbor's insts + itinst = --pb->insts.end(); + + if( pb->blocks.size() > 0 ) { + livevars[0] = 0; livevars[1] = 0; + for( itchild = pb->blocks.begin(); itchild != pb->blocks.end(); ++itchild) { + VuInstruction& front = (*itchild)->insts.front(); + livevars[0] |= front.livevars[0]; + livevars[1] |= front.livevars[1]; + } + + newlive = COMPUTE_LIVE(itinst->addvars[0], itinst->keepvars[0], livevars[0]); + if( itinst->livevars[0] != newlive ) { + changed = TRUE; + itinst->livevars[0] = newlive; + } + + newlive = COMPUTE_LIVE(itinst->addvars[1], itinst->keepvars[1], livevars[1]); + if( itinst->livevars[1] != newlive ) { + changed = TRUE; + itinst->livevars[1] = newlive; + } + } + + while( itinst != pb->insts.begin() ) { + + itnext = itinst; --itnext; + + newlive = COMPUTE_LIVE(itnext->addvars[0], itnext->keepvars[0], itinst->livevars[0]); + + if( itnext->livevars[0] != newlive ) { + changed = TRUE; + itnext->livevars[0] = newlive; + itnext->livevars[1] = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + } + else { + newlive = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + if( itnext->livevars[1] != newlive ) { + changed = TRUE; + itnext->livevars[1] = newlive; + } + } + + itinst = itnext; + } + +// if( (livevars[0] | itinst->livevars[0]) != itinst->livevars[0] ) { +// changed = TRUE; +// itinst->livevars[0] |= livevars[0]; +// } +// if( (livevars[1] | itinst->livevars[1]) != itinst->livevars[1] ) { +// changed = TRUE; +// itinst->livevars[1] |= livevars[1]; +// } +// +// while( itinst != pb->insts.begin() ) { +// +// itnext = itinst; --itnext; +// if( (itnext->livevars[0] | (itinst->livevars[0] & itnext->keepvars[0])) != itnext->livevars[0] ) { +// changed = TRUE; +// itnext->livevars[0] |= itinst->livevars[0] & itnext->keepvars[0]; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// else if( (itnext->livevars[1] | (itinst->livevars[1] & itnext->keepvars[1])) != itnext->livevars[1] ) { +// changed = TRUE; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// +// itinst = itnext; +// } + } + + } while(changed); +} + +static void SuperVUEliminateDeadCode() +{ + list::iterator itblock; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itinst, itnext; + + FORIT(itblock, s_listBlocks) { + +#ifdef _DEBUG + u32 startpc = (*itblock)->startpc; + u32 curpc = startpc; +#endif + + itnext = (*itblock)->insts.begin(); + itinst = itnext++; + while(itnext != (*itblock)->insts.end() ) { + if( itinst->type & INST_DUMMY ) { + itinst->regs[0].VIwrite &= itnext->livevars[0]; + itinst->regs[1].VIwrite &= itnext->livevars[0]; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + VuInstruction* parent = (*itblock)->GetInstAtPc(itinst->nParentPc); + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~INST_CLIP_WRITE; + + if( parent->info.macflag && (itinst->type & INST_MAC_WRITE) ) { + if( !(viwrite&(1<info.macflag = 0; +// parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_MAC_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.statusflag && (itinst->type & INST_STATUS_WRITE)) { + if( !(viwrite&(1<info.statusflag = 0; +// parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_STATUS_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type == 0 ) { + itnext = (*itblock)->insts.erase(itinst); + itinst = itnext++; + continue; + } + } +#ifdef _DEBUG + else curpc += 8; +#endif + itinst = itnext; + ++itnext; + } + + if( itinst->type & INST_DUMMY ) { + // last inst with the children + u32 mask = 0; + for(itchild = (*itblock)->blocks.begin(); itchild != (*itblock)->blocks.end(); ++itchild) { + mask |= (*itchild)->insts.front().livevars[0]; + } + itinst->regs[0].VIwrite &= mask; + itinst->regs[1].VIwrite &= mask; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + if( itinst->nParentPc >= 0 ) { + VuInstruction* parent = (*itblock)->GetInstAtPc(itinst->nParentPc); + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~INST_CLIP_WRITE; + + if( parent->info.macflag ) { + if( !(viwrite&(1<info.macflag = 0; + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_MAC_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type&INST_STATUS_WRITE) ); + + if( parent->info.statusflag ) { + if( !(viwrite&(1<info.statusflag = 0; + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_STATUS_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type&INST_STATUS_WRITE) ); + + if( itinst->type == 0 ) { + (*itblock)->insts.erase(itinst); + } + } + } + } +} + +// assigns xmm/x86 regs to all instructions, ignore mode field +// returns true if changed +bool AlignStartRegsToEndRegs(_xmmregs* startregs, const list& parents) +{ + list::const_iterator itblock, itblock2; + int bestscore; + _xmmregs bestregs; + bool bchanged = false; + + // find the best merge of regs that minimizes writes/reads + for(int i = 0; i < XMMREGS; ++i) { + + bestscore = 1000; + memset(&bestregs, 0, sizeof(bestregs)); + + FORIT(itblock, parents) { + int curscore = 0; + if( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->endregs[i].inuse ) { + int type = (*itblock)->endregs[i].type; + int reg = (*itblock)->endregs[i].reg; + + FORIT(itblock2, parents) { + if( (*itblock2)->type & BLOCKTYPE_ANALYZED ) { + if( (*itblock2)->endregs[i].inuse ) { + if( (*itblock2)->endregs[i].type != type || (*itblock2)->endregs[i].reg != reg ) { + curscore += 1; + } + } + else curscore++; + } + } + } + + if( curscore < 1 && curscore < bestscore ) { + memcpy(&bestregs, &(*itblock)->endregs[i], sizeof(bestregs)); + bestscore = curscore; + } + } + + if( bestscore < 1 ) { + if( startregs[i].inuse == bestregs.inuse ) { + if( bestregs.inuse && (startregs[i].type != bestregs.type || startregs[i].reg != bestregs.reg) ) + bchanged = true; + } + else bchanged = true; + + memcpy(&startregs[i], &bestregs, sizeof(bestregs)); + FORIT(itblock, parents) memcpy(&(*itblock)->endregs[i], &bestregs, sizeof(bestregs)); + } + else { + if( startregs[i].inuse ) bchanged = true; + startregs[i].inuse = 0; + FORIT(itblock, parents) (*itblock)->endregs[i].inuse = 0; + } + } + + return bchanged; +} + +void VuBaseBlock::AssignVFRegs() +{ + int i; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itblock; + list::iterator itinst, itnext, itinst2; + + // init the start regs + if( type & BLOCKTYPE_ANALYZED ) return; // nothing changed + memcpy(xmmregs, startregs, sizeof(xmmregs)); + + if( type & BLOCKTYPE_ANALYZED ) { + // check if changed + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse != startregs[i].inuse ) + break; + if( xmmregs[i].inuse && (xmmregs[i].reg != startregs[i].reg || xmmregs[i].type != startregs[i].type) ) + break; + } + + if( i == XMMREGS ) return; // nothing changed + } + + s8* oldX86 = x86Ptr; + + FORIT(itinst, insts) { + + if( itinst->type & INST_DUMMY ) + continue; + + // reserve, go from upper to lower + for(i = 1; i >= 0; --i) { + _VURegsNum* regs = itinst->regs+i; + + // redo the counters so that the proper regs are released + for(int j = 0; j < XMMREGS; ++j) { + if( xmmregs[j].inuse ) { + if( xmmregs[j].type == XMMTYPE_VFREG ) { + int count = 0; + itinst2 = itinst; + + if( i ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg ) { + itinst2 = insts.end(); + break; + } + else { + ++count; + ++itinst2; + } + } + + while(itinst2 != insts.end() ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg || + itinst2->regs[1].VFread0 == xmmregs[j].reg || itinst2->regs[1].VFread1 == xmmregs[j].reg || itinst2->regs[1].VFwrite == xmmregs[j].reg) + break; + + ++count; + ++itinst2; + } + xmmregs[j].counter = 1000-count; + } + else { + assert( xmmregs[j].type == XMMTYPE_ACC ); + + int count = 0; + itinst2 = itinst; + + if( i ) ++itinst2; // acc isn't used in lower insts + + while(itinst2 != insts.end() ) { + assert( !((itinst2->regs[0].VIread|itinst2->regs[0].VIwrite) & (1<regs[1].VIread|itinst2->regs[1].VIwrite) & (1<VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<vfread0[i] = itinst->vfread1[i] = itinst->vfwrite[i] = itinst->vfacc[i] = -1; + itinst->vfflush[i] = -1; + + if( regs->VFread0 ) itinst->vfread0[i] = _allocVFtoXMMreg(VU, -1, regs->VFread0, 0); + else if( regs->VIread & (1<vfread0[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VFread1 ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, regs->VFread1, 0); + else if( (regs->VIread & (1<VFr1xyzw != 0xff ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VIread & (1<vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + + int reusereg = -1; // 0 - VFwrite, 1 - VFAcc + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwxyzw == 0xf ) { + itinst->vfwrite[i] = _checkXMMreg(XMMTYPE_VFREG, regs->VFwrite, 0); + if( itinst->vfwrite[i] < 0 ) reusereg = 0; + } + else { + itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + else if( regs->VIwrite & (1<VFwxyzw == 0xf ) { + itinst->vfacc[i] = _checkXMMreg(XMMTYPE_ACC, 0, 0); + if( itinst->vfacc[i] < 0 ) reusereg = 1; + } + else { + itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + } + } + + if( reusereg >= 0 ) { + // reuse + itnext = itinst; itnext++; + + u8 type = reusereg ? XMMTYPE_ACC : XMMTYPE_VFREG; + u8 reg = reusereg ? 0 : regs->VFwrite; + + if( itinst->vfacc[i] >= 0 && ((regs->VIread&(1<usedvars[0]&(1<livevars[0]&(1<livevars[0]&(1<vfacc[i]); + xmmregs[itinst->vfacc[i]].inuse = 1; + xmmregs[itinst->vfacc[i]].reg = reg; + xmmregs[itinst->vfacc[i]].type = type; + xmmregs[itinst->vfacc[i]].mode = 0; + itinst->vfwrite[i] = itinst->vfacc[i]; + } + else if( itinst->vfread0[i] >= 0 && (itnext == insts.end() || (regs->VFread0 > 0 && (!(itnext->usedvars[1]&(1<VFread0)) || !(itnext->livevars[1]&(1<VFread0))))) ) { + if(itnext->livevars[1]®s->VFread0) _freeXMMreg(itinst->vfread0[i]); + xmmregs[itinst->vfread0[i]].inuse = 1; + xmmregs[itinst->vfread0[i]].reg = reg; + xmmregs[itinst->vfread0[i]].type = type; + xmmregs[itinst->vfread0[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread0[i]; + else itinst->vfwrite[i] = itinst->vfread0[i]; + } + else if( itinst->vfread1[i] >= 0 && (regs->VFread1 > 0 && (!(itnext->usedvars[1]&(1<VFread1)) || !(itnext->livevars[1]&(1<VFread1)))) ) { + if(itnext->livevars[1]®s->VFread1) _freeXMMreg(itinst->vfread1[i]); + xmmregs[itinst->vfread1[i]].inuse = 1; + xmmregs[itinst->vfread1[i]].reg = reg; + xmmregs[itinst->vfread1[i]].type = type; + xmmregs[itinst->vfread1[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread1[i]; + else itinst->vfwrite[i] = itinst->vfread1[i]; + } + else { + if( reusereg ) itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + else itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + + // always alloc at least 1 temp reg + int free0 = (i||regs->VFwrite||regs->VFread0||regs->VFread1||(regs->VIwrite&(1<vfwrite[1] >= 0 && (itinst->vfread0[0]==itinst->vfwrite[1]||itinst->vfread1[0]==itinst->vfwrite[1]) ) { + itinst->vfflush[i] = _allocTempXMMreg(XMMT_FPS, -1); + } + + if( i == 1 && (regs->VIwrite & (1<VIwrite & (1<vfflush[i] >= 0 ) _freeXMMreg(itinst->vfflush[i]); + if( free0 >= 0 ) _freeXMMreg(free0); + + itinst->vffree[i] = (free0&0xf)|(free1<<8)|(free2<<16); + + _clearNeededXMMregs(); + } + } + + assert( x86Ptr == oldX86 ); + u32 analyzechildren = !(type&BLOCKTYPE_ANALYZED); + type |= BLOCKTYPE_ANALYZED; + + //memset(endregs, 0, sizeof(endregs)); + + if( analyzechildren ) { + FORIT(itchild, blocks) (*itchild)->AssignVFRegs(); + } +} + +struct MARKOVBLANKET +{ + list parents; + list children; +}; + +static MARKOVBLANKET s_markov; + +void VuBaseBlock::AssignVIRegs(int parent) +{ + const int maxregs = 6; + + if( parent ) { + if( (type&BLOCKTYPE_ANALYZEDPARENT) ) + return; + + type |= BLOCKTYPE_ANALYZEDPARENT; + s_markov.parents.push_back(this); + for(LISTBLOCKS::iterator it = blocks.begin(); it != blocks.end(); ++it) { + (*it)->AssignVIRegs(0); + } + return; + } + + if( (type&BLOCKTYPE_ANALYZED) ) + return; + + // child + assert( allocX86Regs == -1 ); + allocX86Regs = s_vecRegArray.size(); + s_vecRegArray.resize(allocX86Regs+X86REGS); + + _x86regs* pregs = &s_vecRegArray[allocX86Regs]; + memset(pregs, 0, sizeof(_x86regs)*X86REGS); + + assert( parents.size() > 0 ); + + list::iterator itparent; + u32 usedvars = insts.front().usedvars[0]; + u32 livevars = insts.front().livevars[0]; + + if( parents.size() > 0 ) { + u32 usedvars2 = 0xffffffff; + FORIT(itparent, parents) usedvars2 &= (*itparent)->insts.front().usedvars[0]; + usedvars |= usedvars2; + } + + usedvars &= livevars; + + // currently order doesn't matter + int num = 0; + + if( usedvars ) { + for(int i = 1; i < 16; ++i) { + if( usedvars & (1<= maxregs ) break; + } + } + } + + if( num < maxregs) { + livevars &= ~usedvars; + livevars &= insts.back().usedvars[0]; + + if( livevars ) { + for(int i = 1; i < 16; ++i) { + if( livevars & (1<= maxregs) break; + } + } + } + } + + s_markov.children.push_back(this); + type |= BLOCKTYPE_ANALYZED; + FORIT(itparent, parents) { + (*itparent)->AssignVIRegs(1); + } +} + +u32 VuBaseBlock::GetModeXYZW(u32 curpc, int vfreg) +{ + if( vfreg <= 0 ) return false; + + list::iterator itinst = insts.begin(); + advance(itinst, (curpc-startpc)/8); + + u8 mxy = 1; + u8 mxyz = 1; + + while(itinst != insts.end()) { + for(int i = 0; i < 2; ++i ) { + if( itinst->regs[i].VFwrite == vfreg ) { + if( itinst->regs[i].VFwxyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFwxyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread0 == vfreg ) { + if( itinst->regs[i].VFr0xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr0xyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread1 == vfreg ) { + if( itinst->regs[i].VFr1xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr1xyzw != 0xc ) mxy = 0; + } + + if( !mxy && !mxyz ) return 0; + } + ++itinst; + } + + return (mxy?MODE_VUXY:0)|(mxyz?MODE_VUXYZ:0); +} + +static void SuperVUAssignRegs() +{ + list::iterator itblock, itblock2; + + // assign xyz regs +// FORIT(itblock, s_listBlocks) { +// (*itblock)->vuxyz = 0; +// (*itblock)->vuxy = 0; +// +// for(int i = 0; i < 32; ++i) { +// u32 mode = (*itblock)->GetModeXYZW((*itblock)->startpc, i); +// if( mode & MODE_VUXYZ ) { +// if( mode & MODE_VUZ ) (*itblock)->vuxyz |= 1<vuxy |= 1<type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->AssignVFRegs(); + + // VI assignments, find markov blanket for each node in the graph + // then allocate regs based on the commonly used ones +#ifdef SUPERVU_X86CACHING + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~(BLOCKTYPE_ANALYZED|BLOCKTYPE_ANALYZEDPARENT); + s_vecRegArray.resize(0); + u8 usedregs[16]; + + // note: first block always has to start with no alloc regs + bool bfirst = true; + + FORIT(itblock, s_listBlocks) { + + if( !((*itblock)->type & BLOCKTYPE_ANALYZED) ) { + + if( (*itblock)->parents.size() == 0 ) { + (*itblock)->type |= BLOCKTYPE_ANALYZED; + bfirst = false; + continue; + } + + s_markov.children.clear(); + s_markov.parents.clear(); + (*itblock)->AssignVIRegs(0); + + // assign the regs + int regid = s_vecRegArray.size(); + s_vecRegArray.resize(regid+X86REGS); + + _x86regs* mergedx86 = &s_vecRegArray[regid]; + memset(mergedx86, 0, sizeof(_x86regs)*X86REGS); + + if( !bfirst ) { + *(u32*)usedregs = *((u32*)usedregs+1) = *((u32*)usedregs+2) = *((u32*)usedregs+3) = 0; + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->allocX86Regs >= 0 ); + _x86regs* pregs = &s_vecRegArray[(*itblock2)->allocX86Regs]; + for(int i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse && pregs[i].reg < 16) { + //assert( pregs[i].reg < 16); + usedregs[pregs[i].reg]++; + } + } + } + + int num = 1; + for(int i = 0; i < 16; ++i) { + if( usedregs[i] == s_markov.children.size() ) { + // use + mergedx86[num].inuse = 1; + mergedx86[num].reg = i; + mergedx86[num].type = (s_vu?X86TYPE_VU1:0)|X86TYPE_VI; + mergedx86[num].mode = MODE_READ; + if( ++num >= X86REGS ) + break; + if( num == ESP ) + ++num; + } + } + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->nStartx86 == -1 ); + (*itblock2)->nStartx86 = regid; + } + + FORIT(itblock2, s_markov.parents) { + assert( (*itblock2)->nEndx86 == -1 ); + (*itblock2)->nEndx86 = regid; + } + } + + bfirst = false; + } + } +#endif +} + +////////////////// +// Recompilation +////////////////// +static u32 s_TotalVUCycles; // total cycles since start of program execution + +// cycles in which the last Q,P regs were finished (written to VU->VI[]) +// the write occurs before the instruction is executed at that cycle +// compare with s_TotalVUCycles +// if less than 0, already flushed +static int s_writeQ, s_writeP; +static int s_recWriteQ, s_recWriteP; // wait times during recompilation +static int s_needFlush; // first bit - Q, second bit - P, third bit - Q has been written, fourth bit - P has been written + +static u32 s_vu1ebp, s_vu1esp, s_vu1esi, s_callstack;//, s_vu1esp +static u32 s_ssecsr; +static int s_JumpX86; + +//extern "C" u32 g_sseVUMXCSR; + +// entry point of all vu programs from emulator calls +__declspec(naked) void SuperVUExecuteProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svubase); +#endif + __asm { + mov eax, dword ptr [esp] + add esp, 4 + mov s_callstack, eax + call SuperVUGetProgram + + // save cpu state + mov s_vu1ebp, ebp + mov s_vu1esi, esi // have to save even in Release + } +#ifdef _DEBUG + __asm { + mov s_vu1esp, esp + } +#endif + + __asm { +// stmxcsr s_ssecsr +// ldmxcsr g_sseVUMXCSR + + // init vars + xor ecx, ecx + mov s_writeQ, 0xffffffff + mov s_writeP, 0xffffffff + mov s_TotalVUCycles, ecx + + jmp eax + } +} + +static void SuperVUCleanupProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +#endif + +#ifdef _DEBUG + assert( s_vu1esp == 0 ); +#endif + + VU = vuindex ? &VU1 : &VU0; + VU->cycle += s_TotalVUCycles; + if( (int)s_writeQ > 0 ) VU->VI[REG_Q] = VU->q; + if( (int)s_writeP > 0 ) { + assert(VU == &VU1); + VU1.VI[REG_P] = VU1.p; // only VU1 + } +} + +// exit point of all vu programs +__declspec(naked) static void SuperVUEndProgram() +{ + __asm { + // restore cpu state + //ldmxcsr s_ssecsr + + mov ebp, s_vu1ebp + mov esi, s_vu1esi + } + +#ifdef _DEBUG + __asm { + sub s_vu1esp, esp + } +#endif + + __asm { + call SuperVUCleanupProgram + jmp s_callstack // so returns correctly + } +} + +// Flushes P/Q regs +void SuperVUFlush(int p, int wait) +{ + u8* pjmp[3]; + if( !(s_needFlush&(1<info.cycle < recwait ) return; + + if( recwait == 0 ) { + // write didn't happen this block + MOV32MtoR(EAX, p ? (u32)&s_writeP : (u32)&s_writeQ); + OR32RtoR(EAX, EAX); + pjmp[0] = JS8(0); + + if( s_pCurInst->info.cycle ) SUB32ItoR(EAX, s_pCurInst->info.cycle); + + // if writeQ <= total+offset + if( !wait ) { // only write back if time is up + CMP32MtoR(EAX, (u32)&s_TotalVUCycles); + pjmp[1] = JG8(0); + } + else { + // add (writeQ-total-offset) to s_TotalVUCycles + // necessary? + CMP32MtoR(EAX, (u32)&s_TotalVUCycles); + pjmp[2] = JLE8(0); + MOV32RtoM((u32)&s_TotalVUCycles, EAX); + x86SetJ8(pjmp[2]); + } + } + else if( wait && s_pCurInst->info.cycle < recwait ) { + MOV32ItoM((u32)&s_TotalVUCycles, recwait); + } + + MOV32MtoR(EAX, SuperVUGetVIAddr(p?REG_P:REG_Q, 0)); + MOV32ItoM(p ? (u32)&s_writeP : (u32)&s_writeQ, 0x80000000); + MOV32RtoM(SuperVUGetVIAddr(p?REG_P:REG_Q, 1), EAX); + + if( recwait == 0 ) { + if( !wait ) x86SetJ8(pjmp[1]); + x86SetJ8(pjmp[0]); + } + + if( wait || (!p && recwait == 0 && s_pCurInst->info.cycle >= 12) || (!p && recwait > 0 && s_pCurInst->info.cycle >= recwait ) ) + s_needFlush &= ~(1<::iterator itblock; + + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->Recompile(); + // make sure everything compiled + FORIT(itblock, s_listBlocks) assert( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->pcode != NULL ); + + // link all blocks + FORIT(itblock, s_listBlocks) { + VuBaseBlock::LISTBLOCKS::iterator itchild; + + assert( (*itblock)->blocks.size() <= ARRAYSIZE((*itblock)->pChildJumps) ); + + int i = 0; + FORIT(itchild, (*itblock)->blocks) { + + if( (u32)(*itblock)->pChildJumps[i] == 0xffffffff ) + continue; + + if( (*itblock)->pChildJumps[i] == NULL ) { + VuBaseBlock* pchild = *itchild; + + if( pchild->type & BLOCKTYPE_HASEOP) { + assert( pchild->blocks.size() == 0); + + AND32ItoM( (u32)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (u32)&VU->vifRegs->stat, ~0x4 ); + + MOV32ItoM((u32)&VU->VI[REG_TPC], pchild->endpc); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + } + // only other case is when there are two branches + else assert( (*itblock)->insts.back().regs[0].pipe == VUPIPE_BRANCH ); + + continue; + } + + if( (u32)(*itblock)->pChildJumps[i] & 0x80000000 ) { + // relative + *(u32*)&(*itblock)->pChildJumps[i] &= 0x7fffffff; + *(*itblock)->pChildJumps[i] = (u32)(*itchild)->pcode - ((u32)(*itblock)->pChildJumps[i] + 4); + } + else *(*itblock)->pChildJumps[i] = (u32)(*itchild)->pcode; + + ++i; + } + } + + s_pFnHeader->pprogfunc = s_listBlocks.front()->pcode; +} + +static u32 s_svulast = 0, s_vufnheader; +extern "C" u32 s_vucount = 0; +static u32 lastrec = 0; +static u32 s_saveecx, s_saveedx, s_saveebx, s_saveesi, s_saveedi, s_saveebp; +static u32 badaddrs[][2] = {0,0 }; + +__declspec(naked) static void svudispfn() +{ + static u32 i; + static u32 curvu; + + __asm { + mov curvu, eax + mov s_saveecx, ecx + mov s_saveedx, edx + mov s_saveebx, ebx + mov s_saveesi, esi + mov s_saveedi, edi + mov s_saveebp, ebp + } + +// for(i = 1; i < 32; ++i) { +// if( (VU1.VF[i].UL[3]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[3] &= 0xff7fffff; +// if( (VU1.VF[i].UL[2]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[2] &= 0xff7fffff; +// if( (VU1.VF[i].UL[1]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[1] &= 0xff7fffff; +// if( (VU1.VF[i].UL[0]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[0] &= 0xff7fffff; +// } + + if( (vudump&8) ) { //&& lastrec != g_vu1last ) { + + for(i = 0; i < ARRAYSIZE(badaddrs); ++i) { + if( s_svulast == badaddrs[i][1] && lastrec == badaddrs[i][0] ) + break; + } + + if( i == ARRAYSIZE(badaddrs) ) + { + __Log("tVU: %x\n", s_svulast); + if( curvu ) iDumpVU1Registers(); + else iDumpVU0Registers(); + s_vucount++; + } + + lastrec = s_svulast; + } + + __asm { + mov ecx, s_saveecx + mov edx, s_saveedx + mov ebx, s_saveebx + mov esi, s_saveesi + mov edi, s_saveedi + mov ebp, s_saveebp + ret + } +} + +// frees an xmmreg depending on the liveness info of hte current inst +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg) +//{ +// if( !xmmregs[xmmreg].inuse ) return; +// if( xmmregs[xmmreg].type == xmmtype && xmmregs[xmmreg].reg == reg ) return; +// +// if( s_pNextInst == NULL ) { +// // last inst, free +// _freeXMMreg(xmmreg); +// return; +// } +// +// if( xmmregs[xmmreg].type == XMMTYPE_VFREG ) { +// if( (s_pCurInst->livevars[1]|s_pNextInst->livevars[1]) & (1<livevars[0]|s_pNextInst->livevars[0]) & (1<VF[xmmregs[i].reg] : (u32)&VU->ACC; + + if( xmmregs[i].mode & MODE_VUZ ) { + SSE_MOVHPS_XMM_to_M64(addr, (x86SSERegType)i); + SSE_SHUFPS_M128_to_XMM((x86SSERegType)i, addr, 0xc4); + } + else SSE_MOVHPS_M64_to_XMM((x86SSERegType)i, addr+8); + + xmmregs[i].mode &= ~MODE_VUXYZ; + } + + _freeXMMreg(i); + } + } + } + + //_freeXMMregs(); +} + +//void timeout() { SysPrintf("VU0 timeout\n"); } +void SuperVUTestVU0Condition(u32 incstack) +{ + if( s_vu ) return; // vu0 only + + CMP32ItoM((u32)&s_TotalVUCycles, 512); // sometimes games spin on vu0, so be careful with this value + // woody hangs if too high + + if( incstack ) { + u8* ptr = JB8(0); + + if( incstack ) ADD32ItoR(ESP, incstack); + //CALLFunc((u32)timeout); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + + x86SetJ8(ptr); + } + else { + JAE32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 6 ) ); + } +} + +void VuBaseBlock::Recompile() +{ + if( type & BLOCKTYPE_ANALYZED ) return; + + x86Align(16); + pcode = x86Ptr; + +#ifdef _DEBUG + MOV32ItoM((u32)&s_vufnheader, s_pFnHeader->startpc); + MOV32ItoM((u32)&VU->VI[REG_TPC], startpc); + MOV32ItoM((u32)&s_svulast, startpc); + MOV32ItoR(EAX, s_vu); + CALLFunc((u32)svudispfn); +#endif + + s_pCurBlock = this; + s_needFlush = 3; + pc = startpc; + branch = 0; + s_recWriteQ = s_recWriteP = 0; + + s_ClipRead = s_PrevClipWrite = (u32)&VU->VI[REG_CLIP_FLAG]; + s_StatusRead = s_PrevStatusWrite = (u32)&VU->VI[REG_STATUS_FLAG]; + s_PrevIWrite = (u32)&VU->VI[REG_I]; + s_MACRead = (u32)&VU->VI[REG_MAC_FLAG]; + s_JumpX86 = 0; + + memcpy(xmmregs, startregs, sizeof(xmmregs)); +#ifdef SUPERVU_X86CACHING + if( nStartx86 >= 0 ) + memcpy(x86regs, &s_vecRegArray[nStartx86], sizeof(x86regs)); + else _initX86regs(); +#else + _initX86regs(); +#endif + + list::iterator itinst; + FORIT(itinst, insts) { + s_pCurInst = &(*itinst); + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + itinst->Recompile(itinst, vuxyz); + } + assert( pc == endpc ); + + // flush flags + if( s_ClipRead != (u32)&VU->VI[REG_CLIP_FLAG] ) { + MOV32MtoR(EAX, s_ClipRead); + MOV32RtoM((u32)&VU->VI[REG_CLIP_FLAG], EAX); + } + if( s_StatusRead != (u32)&VU->VI[REG_STATUS_FLAG] ) { + MOV32MtoR(EAX, s_StatusRead); + MOV32RtoM((u32)&VU->VI[REG_STATUS_FLAG], EAX); + } + if( s_MACRead != (u32)&VU->VI[REG_MAC_FLAG] ) { + MOV32MtoR(EAX, s_MACRead); + MOV32RtoM((u32)&VU->VI[REG_MAC_FLAG], EAX); + } + if( s_PrevIWrite != (u32)&VU->VI[REG_I] ) { + MOV32ItoM((u32)&VU->VI[REG_I], *(u32*)s_PrevIWrite); // never changes + } + + ADD32ItoM((u32)&s_TotalVUCycles, cycles); + + // compute branches, jumps, eop + if( type & BLOCKTYPE_HASEOP ) { + // end + _freeXMMregs(); + _freeX86regs(); + AND32ItoM( (u32)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (u32)&VU->vifRegs->stat, ~0x4 ); + if( !branch ) MOV32ItoM((u32)&VU->VI[REG_TPC], endpc); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + } + else { + + u32 livevars[2] = {0}; + + list::iterator lastinst = GetInstIterAtPc(endpc-8); + lastinst++; + + if( lastinst != insts.end() ) { + livevars[0] = lastinst->livevars[0]; + livevars[1] = lastinst->livevars[1]; + } + else { + // take from children + if( blocks.size() > 0 ) { + LISTBLOCKS::iterator itchild; + FORIT(itchild, blocks) { + livevars[0] |= (*itchild)->insts.front().livevars[0]; + livevars[1] |= (*itchild)->insts.front().livevars[1]; + } + } + else { + livevars[0] = ~0; + livevars[1] = ~0; + } + } + + SuperVUFreeXMMregs(livevars); + + // get rid of any writes, otherwise _freeX86regs will write + x86regs[s_JumpX86].mode &= ~MODE_WRITE; + + if( branch == 1 ) { + if( !x86regs[s_JumpX86].inuse ) { + assert( x86regs[s_JumpX86].type == X86TYPE_VUJUMP ); + s_JumpX86 = 0xffffffff; // notify to jump from g_recWriteback + } + } + + // align VI regs +#ifdef SUPERVU_X86CACHING + if( nEndx86 >= 0 ) { + _x86regs* endx86 = &s_vecRegArray[nEndx86]; + for(int i = 0; i < X86REGS; ++i) { + if( endx86[i].inuse ) { + + if( s_JumpX86 == i && x86regs[s_JumpX86].inuse ) { + x86regs[s_JumpX86].inuse = 0; + x86regs[EAX].inuse = 1; + MOV32RtoR(EAX, s_JumpX86); + s_JumpX86 = EAX; + } + + if( x86regs[i].inuse ) { + if( x86regs[i].type == endx86[i].type && x86regs[i].reg == endx86[i].reg ) { + _freeX86reg(i); + // will continue to use it + continue; + } + + if( x86regs[i].type == (X86TYPE_VI|(s_vu?X86TYPE_VU1:0)) ) { +#ifdef SUPERVU_INTERCACHING + if( livevars[0] & (1<Recompile(); + } +} + +#define GET_VUXYZMODE(reg) 0//((vuxyz&(1<<(reg)))?MODE_VUXYZ:0) + +int VuInstruction::SetCachedRegs(int upper, u32 vuxyz) +{ + if( vfread0[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread0[upper], XMMTYPE_VFREG, regs[upper].VFread0); + _allocVFtoXMMreg(VU, vfread0[upper], regs[upper].VFread0, MODE_READ|GET_VUXYZMODE(regs[upper].VFread0)); + } + if( vfread1[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread1[upper], XMMTYPE_VFREG, regs[upper].VFread1); + _allocVFtoXMMreg(VU, vfread1[upper], regs[upper].VFread1, MODE_READ|GET_VUXYZMODE(regs[upper].VFread1)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIread&(1<= 0 ) { + assert( regs[upper].VFwrite > 0); + SuperVUFreeXMMreg(vfwrite[upper], XMMTYPE_VFREG, regs[upper].VFwrite); + _allocVFtoXMMreg(VU, vfwrite[upper], regs[upper].VFwrite, + MODE_WRITE|(regs[upper].VFwxyzw != 0xf?MODE_READ:0)|GET_VUXYZMODE(regs[upper].VFwrite)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIwrite&(1<= 0 ) info |= PROCESS_EE_SET_S(vfread0[upper]); + if( vfread1[upper] >= 0 ) info |= PROCESS_EE_SET_T(vfread1[upper]); + if( vfacc[upper] >= 0 ) info |= PROCESS_VU_SET_ACC(vfacc[upper]); + if( vfwrite[upper] >= 0 ) { + if( regs[upper].VFwrite == _Ft_ && vfread1[upper] < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite[upper]); + } + else { + assert( regs[upper].VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite[upper]); + } + } + + if( (vffree[upper]&0xf) < XMMREGS ) { + SuperVUFreeXMMreg(vffree[upper]&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vffree[upper]&0xf); + } + info |= PROCESS_VU_SET_TEMP(vffree[upper]&0xf); + + if( vfflush[upper] >= 0 ) { + SuperVUFreeXMMreg(vfflush[upper], XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vfflush[upper]); + } + + if( upper && (regs[upper].VIwrite & (1 << REG_CLIP_FLAG)) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + assert( vfwrite[upper] == -1 ); + SuperVUFreeXMMreg((vffree[upper]>>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + + SuperVUFreeXMMreg((vffree[upper]>>16)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>16)&0xf); + info |= PROCESS_EE_SET_ACC((vffree[upper]>>16)&0xf); + + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + _freeXMMreg((vffree[upper]>>16)&0xf); // don't need anymore + } + else if( regs[upper].VIwrite & (1<>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + } + + if( vfflush[upper] >= 0 ) _freeXMMreg(vfflush[upper]); + if( (vffree[upper]&0xf) < XMMREGS ) _freeXMMreg(vffree[upper]&0xf); // don't need anymore + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<::const_iterator& itinst, u32 vuxyz) +{ + __declspec(align(16)) static VECTOR _VF, _VFc; + u32 *ptr; + u8* pjmp; + int vfregstore=0, viregstore=0; + + assert( s_pCurInst == this); + s_WriteToReadQ = 0; + + ptr = (u32*)&VU->Micro[ pc ]; + + if( type & INST_Q_READ ) + SuperVUFlush(0, (ptr[0] == 0x800003bf)||!!(regs[0].VIwrite & (1<GetInstAtPc(nParentPc); + s_ClipRead = parent->pClipWrite; + } + + // before modifying, check if they will ever be read + if( s_pCurBlock->type & BLOCKTYPE_MACFLAGS ) { + if( type & INST_STATUS_WRITE ) { + parent = s_pCurBlock->GetInstAtPc(nParentPc); + s_StatusRead = parent->pStatusWrite; + } + if( type & INST_MAC_WRITE ) { + parent = s_pCurBlock->GetInstAtPc(nParentPc); + s_MACRead = parent->pMACWrite; + } + } + + assert( s_ClipRead != 0 ); + assert( s_MACRead != 0 ); + assert( s_StatusRead != 0 ); + return; + } + +#ifdef _DEBUG +// CMP32ItoM((u32)ptr, ptr[0]); +// j8Ptr[0] = JNE8(0); +// CMP32ItoM((u32)(ptr+1), ptr[1]); +// j8Ptr[1] = JNE8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[0] ); +// x86SetJ8( j8Ptr[1] ); +// PUSH32I(ptr[0]); +// PUSH32I(s_vu); +// PUSH32I(pc); +// CALLFunc((u32)checkvucodefn); +// ADD32ItoR(ESP, 12); +// x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoR(EAX, pc); +#endif + + assert( !(type & (INST_CLIP_WRITE|INST_STATUS_WRITE|INST_MAC_WRITE)) ); + pc += 8; + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<type & BLOCKTYPE_MACFLAGS ) { + pMACWrite = (u32)SuperVUStaticAlloc(4); + pStatusWrite = (u32)SuperVUStaticAlloc(4); + } + else { + assert( s_StatusRead == (u32)&VU->VI[REG_STATUS_FLAG] ); + assert( s_MACRead == (u32)&VU->VI[REG_MAC_FLAG] ); + pMACWrite = s_MACRead; + pStatusWrite = s_StatusRead; + } + } + + if( (regs[0].VIwrite|regs[1].VIwrite) & (1<::const_iterator itinst2; + +#ifdef SUPERVU_X86CACHING + // redo the counters so that the proper regs are released + for(int j = 0; j < X86REGS; ++j) { + if( x86regs[j].inuse && X86_ISVI(x86regs[j].type) ) { + int count = 0; + itinst2 = itinst; + + while(itinst2 != s_pCurBlock->insts.end() ) { + if( (itinst2->regs[0].VIread|itinst2->regs[0].VIwrite|itinst2->regs[1].VIread|itinst2->regs[1].VIwrite) && (1<flags, VUFLAG_MFLAGSET); + } + if (ptr[1] & 0x10000000) { // D flag + TEST32ItoM((u32)&VU0.VI[REG_FBRST].UL, s_vu?0x400:0x004); + u8* ptr = JZ8(0); + OR32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x200:0x002); + PUSH32I(s_vu?INTC_VU1:INTC_VU0); + CALLFunc((u32)hwIntcIrq); + ADD32ItoR(ESP, 4); + x86SetJ8(ptr); + } + if (ptr[1] & 0x08000000) { // T flag + TEST32ItoM((u32)&VU0.VI[REG_FBRST].UL, s_vu?0x800:0x008); + u8* ptr = JZ8(0); + OR32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x400:0x004); + PUSH32I(s_vu?INTC_VU1:INTC_VU0); + CALLFunc((u32)hwIntcIrq); + ADD32ItoR(ESP, 4); + x86SetJ8(ptr); + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + + assert( !(regs[0].VIwrite & ((1<code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + + s_PrevIWrite = (u32)ptr; + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + else { + if( regs[0].VIwrite & (1<insts.end()); + u32* codeptr2 = ptr+2; + + while(itinst2 != s_pCurBlock->insts.end() ) { + if( !(itinst2->type & INST_DUMMY) && ((itinst2->regs[0].VIwrite&(1<type & INST_Q_WRITE) && itinst2->nParentPc == pc-8 ) { + break; + } + if( itinst2->type & INST_Q_READ ) { + cacheq = 1; + break; + } + if( itinst2->type & INST_DUMMY ) { + ++itinst2; + continue; + } + codeptr2 += 2; + ++itinst2; + } + + if( itinst2 == s_pCurBlock->insts.end() ) + cacheq = 1; + + int x86temp = -1; + if( cacheq ) + x86temp = _allocX86reg(-1, X86TYPE_TEMP, 0, 0); + + // new is written so flush old + // if type & INST_Q_READ, already flushed + if( !(type & INST_Q_READ) && s_recWriteQ == 0 ) MOV32MtoR(EAX, (u32)&s_writeQ); + + if( cacheq ) + MOV32MtoR(x86temp, (u32)&s_TotalVUCycles); + + if( !(type & INST_Q_READ) ) { + if( s_recWriteQ == 0 ) { + OR32RtoR(EAX, EAX); + pjmp = JS8(0); + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + x86SetJ8(pjmp); + } + else if( s_needFlush & 1 ) { + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + s_needFlush &= ~1; + } + } + + // write new Q + if( cacheq ) { + assert(s_pCurInst->pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((u32)&s_writeQ, x86temp); + s_needFlush |= 1; + } + else { + // won't be writing back + s_WriteToReadQ = 1; + s_needFlush &= ~1; + MOV32ItoM((u32)&s_writeQ, 0x80000001); + } + + s_recWriteQ = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + if( x86temp >= 0 ) + _freeX86reg(x86temp); + } + + if( regs[0].VIwrite & (1<pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((u32)&s_writeP, x86temp); + s_needFlush |= 2; + + s_recWriteP = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + _freeX86reg(x86temp); + } + + if( ptr[0] == 0x800003bf ) // waitq + SuperVUFlush(0, 1); + + if( ptr[0] == 0x800007bf ) // waitp + SuperVUFlush(1, 1); + +#ifdef PCSX2_DEVBUILD + if ( regs[1].VIread & regs[0].VIwrite & ~((1<startpc); + } +#endif + + u32 modewrite = 0; + if( xmmregs[vfwrite[1]].inuse && xmmregs[vfwrite[1]].type == XMMTYPE_VFREG && xmmregs[vfwrite[1]].reg == regs[1].VFwrite ) + modewrite = xmmregs[vfwrite[1]].mode & MODE_WRITE; + + VU->code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + + if (vfwrite[1] >= 0) { + assert( regs[1].VFwrite > 0 ); + + if (vfwrite[0] == vfwrite[1]) { + //SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle %x\n", s_pCurBlock->startpc); + } + + if (vfread0[0] == vfwrite[1] || vfread1[0] == vfwrite[1] ) { + assert( regs[0].VFread0 == regs[1].VFwrite || regs[0].VFread1 == regs[1].VFwrite ); + assert( vfflush[0] >= 0 ); + if( modewrite ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[regs[1].VFwrite], (x86SSERegType)vfwrite[1]); + } + vfregstore = 1; + } + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + _clearNeededXMMregs(); + _clearNeededX86regs(); + + VU->code = ptr[0]; + s_vuInfo = SetCachedRegs(0, vuxyz); + + if( vfregstore ) { + // load + SSE_MOVAPS_M128_to_XMM(vfflush[0], (u32)&VU->VF[regs[1].VFwrite]); + + assert( xmmregs[vfwrite[1]].mode & MODE_WRITE ); + + // replace with vfflush + if( _Fs_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_S(0xf); + s_vuInfo |= PROCESS_EE_SET_S(vfflush[0]); + } + if( _Ft_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_T(0xf); + s_vuInfo |= PROCESS_EE_SET_T(vfflush[0]); + } + + xmmregs[vfflush[0]].mode |= MODE_NOFLUSH|MODE_WRITE; // so that lower inst doesn't flush + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + + recSVU_LOWER_OPCODE[ VU->code >> 25 ](); + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + + // clip is always written so ok + if( (regs[0].VIwrite|regs[1].VIwrite) & (1<code); + int curjump = 0; + + if( s_pCurInst->type & INST_BRANCH_DELAY ) { + assert( (branch&7)!=2 && (branch&7)!=4 ); // no jump handlig for now + + if( (branch & 0x7) == 3 ) { + // previous was a direct jump + curjump = 1; + } + else if( branch & 1 ) curjump = 2; + } + + assert( s_JumpX86 > 0 ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump] = (u32*)x86Ptr-1; + + if( !(s_pCurInst->type & INST_BRANCH_DELAY) ) { + j8Ptr[1] = JMP8(0); + x86SetJ8( j8Ptr[ 0 ] ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), pc); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump+1] = (u32*)x86Ptr-1; + + x86SetJ8( j8Ptr[ 1 ] ); + } + else + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +// supervu specific insts +void recSVUMI_IBQ_prep() +{ + int fsreg, ftreg; + + if( _Fs_ == 0 ) { + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( ftreg >= 0 ) { + CMP16ItoR( ftreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Ft_, 1), 0); + } + else if( _Ft_ == 0 ) { + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR( fsreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Fs_, 1), 0); + } + else { + _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_); + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + if( ftreg >= 0 ) { + CMP16RtoR( fsreg, ftreg ); + } + else CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + else if( ftreg >= 0 ) { + CMP16MtoR(ftreg, SuperVUGetVIAddr(_Fs_, 1)); + } + else { + fsreg = _allocX86reg(-1, X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + } +} + +void recSVUMI_IBEQ() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JNE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + } + + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JLE8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JG8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JNS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBNE() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_B() +{ + // supervu will take care of the rest + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[0] = (u32*)x86Ptr-1; + } + + branch |= 3; +} + +void recSVUMI_BAL() +{ + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[0] = (u32*)x86Ptr-1; + } + + branch |= 3; +} + +void recSVUMI_JR() +{ + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { + PUSH32I(s_vu); + PUSH32R(EAX); + } + branch |= 2; +} + +void recSVUMI_JALR() +{ + _addNeededX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_); + + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); // necessary, charlie and chocolate factory gives bad addrs, but graphics are ok + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { + PUSH32I(s_vu); + PUSH32R(EAX); + } + + branch |= 4; +} + +#ifdef SUPERVU_COUNT +void StopSVUCounter() +{ + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +} + +void StartSVUCounter() +{ + QueryPerformanceCounter(&svubase); +} +#endif + +//extern u32 vudump; +//void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 766 ) { +// vudump |= 8; +// } +//} + +void recSVUMI_XGKICK( VURegs *VU, int info ) +{ + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + _freeX86reg(fsreg); + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + + _freeX86regs(); + _freeXMMregs(); + + PUSH32R(fsreg); + PUSH32I((int)VU->Mem); + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StopSVUCounter); +#endif + + //CALLFunc((u32)countfn); + + if( CHECK_MULTIGS ) { + CALLFunc((int)VU1XGKICK_MTGSTransfer); + ADD32ItoR(ESP, 8); + } + else { + CALLFunc((int)GSgifTransfer1); + } + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StartSVUCounter); +#endif +} + +// upper inst +void recSVUMI_ABS() { recVUMI_ABS(VU, s_vuInfo); } + +void recSVUMI_ADD() { recVUMI_ADD(VU, s_vuInfo); } +void recSVUMI_ADDi() { recVUMI_ADDi(VU, s_vuInfo); } +void recSVUMI_ADDq() { recVUMI_ADDq(VU, s_vuInfo); } +void recSVUMI_ADDx() { recVUMI_ADDx(VU, s_vuInfo); } +void recSVUMI_ADDy() { recVUMI_ADDy(VU, s_vuInfo); } +void recSVUMI_ADDz() { recVUMI_ADDz(VU, s_vuInfo); } +void recSVUMI_ADDw() { recVUMI_ADDw(VU, s_vuInfo); } + +void recSVUMI_ADDA() { recVUMI_ADDA(VU, s_vuInfo); } +void recSVUMI_ADDAi() { recVUMI_ADDAi(VU, s_vuInfo); } +void recSVUMI_ADDAq() { recVUMI_ADDAq(VU, s_vuInfo); } +void recSVUMI_ADDAx() { recVUMI_ADDAx(VU, s_vuInfo); } +void recSVUMI_ADDAy() { recVUMI_ADDAy(VU, s_vuInfo); } +void recSVUMI_ADDAz() { recVUMI_ADDAz(VU, s_vuInfo); } +void recSVUMI_ADDAw() { recVUMI_ADDAw(VU, s_vuInfo); } + +void recSVUMI_SUB() { recVUMI_SUB(VU, s_vuInfo); } +void recSVUMI_SUBi() { recVUMI_SUBi(VU, s_vuInfo); } +void recSVUMI_SUBq() { recVUMI_SUBq(VU, s_vuInfo); } +void recSVUMI_SUBx() { recVUMI_SUBx(VU, s_vuInfo); } +void recSVUMI_SUBy() { recVUMI_SUBy(VU, s_vuInfo); } +void recSVUMI_SUBz() { recVUMI_SUBz(VU, s_vuInfo); } +void recSVUMI_SUBw() { recVUMI_SUBw(VU, s_vuInfo); } + +void recSVUMI_SUBA() { recVUMI_SUBA(VU, s_vuInfo); } +void recSVUMI_SUBAi() { recVUMI_SUBAi(VU, s_vuInfo); } +void recSVUMI_SUBAq() { recVUMI_SUBAq(VU, s_vuInfo); } +void recSVUMI_SUBAx() { recVUMI_SUBAx(VU, s_vuInfo); } +void recSVUMI_SUBAy() { recVUMI_SUBAy(VU, s_vuInfo); } +void recSVUMI_SUBAz() { recVUMI_SUBAz(VU, s_vuInfo); } +void recSVUMI_SUBAw() { recVUMI_SUBAw(VU, s_vuInfo); } + +void recSVUMI_MUL() { recVUMI_MUL(VU, s_vuInfo); } +void recSVUMI_MULi() { recVUMI_MULi(VU, s_vuInfo); } +void recSVUMI_MULq() { recVUMI_MULq(VU, s_vuInfo); } +void recSVUMI_MULx() { recVUMI_MULx(VU, s_vuInfo); } +void recSVUMI_MULy() { recVUMI_MULy(VU, s_vuInfo); } +void recSVUMI_MULz() { recVUMI_MULz(VU, s_vuInfo); } +void recSVUMI_MULw() { recVUMI_MULw(VU, s_vuInfo); } + +void recSVUMI_MULA() { recVUMI_MULA(VU, s_vuInfo); } +void recSVUMI_MULAi() { recVUMI_MULAi(VU, s_vuInfo); } +void recSVUMI_MULAq() { recVUMI_MULAq(VU, s_vuInfo); } +void recSVUMI_MULAx() { recVUMI_MULAx(VU, s_vuInfo); } +void recSVUMI_MULAy() { recVUMI_MULAy(VU, s_vuInfo); } +void recSVUMI_MULAz() { recVUMI_MULAz(VU, s_vuInfo); } +void recSVUMI_MULAw() { recVUMI_MULAw(VU, s_vuInfo); } + +void recSVUMI_MADD() { recVUMI_MADD(VU, s_vuInfo); } +void recSVUMI_MADDi() { recVUMI_MADDi(VU, s_vuInfo); } +void recSVUMI_MADDq() { recVUMI_MADDq(VU, s_vuInfo); } +void recSVUMI_MADDx() { recVUMI_MADDx(VU, s_vuInfo); } +void recSVUMI_MADDy() { recVUMI_MADDy(VU, s_vuInfo); } +void recSVUMI_MADDz() { recVUMI_MADDz(VU, s_vuInfo); } +void recSVUMI_MADDw() { recVUMI_MADDw(VU, s_vuInfo); } + +void recSVUMI_MADDA() { recVUMI_MADDA(VU, s_vuInfo); } +void recSVUMI_MADDAi() { recVUMI_MADDAi(VU, s_vuInfo); } +void recSVUMI_MADDAq() { recVUMI_MADDAq(VU, s_vuInfo); } +void recSVUMI_MADDAx() { recVUMI_MADDAx(VU, s_vuInfo); } +void recSVUMI_MADDAy() { recVUMI_MADDAy(VU, s_vuInfo); } +void recSVUMI_MADDAz() { recVUMI_MADDAz(VU, s_vuInfo); } +void recSVUMI_MADDAw() { recVUMI_MADDAw(VU, s_vuInfo); } + +void recSVUMI_MSUB() { recVUMI_MSUB(VU, s_vuInfo); } +void recSVUMI_MSUBi() { recVUMI_MSUBi(VU, s_vuInfo); } +void recSVUMI_MSUBq() { recVUMI_MSUBq(VU, s_vuInfo); } +void recSVUMI_MSUBx() { recVUMI_MSUBx(VU, s_vuInfo); } +void recSVUMI_MSUBy() { recVUMI_MSUBy(VU, s_vuInfo); } +void recSVUMI_MSUBz() { recVUMI_MSUBz(VU, s_vuInfo); } +void recSVUMI_MSUBw() { recVUMI_MSUBw(VU, s_vuInfo); } + +void recSVUMI_MSUBA() { recVUMI_MSUBA(VU, s_vuInfo); } +void recSVUMI_MSUBAi() { recVUMI_MSUBAi(VU, s_vuInfo); } +void recSVUMI_MSUBAq() { recVUMI_MSUBAq(VU, s_vuInfo); } +void recSVUMI_MSUBAx() { recVUMI_MSUBAx(VU, s_vuInfo); } +void recSVUMI_MSUBAy() { recVUMI_MSUBAy(VU, s_vuInfo); } +void recSVUMI_MSUBAz() { recVUMI_MSUBAz(VU, s_vuInfo); } +void recSVUMI_MSUBAw() { recVUMI_MSUBAw(VU, s_vuInfo); } + +void recSVUMI_MAX() { recVUMI_MAX(VU, s_vuInfo); } +void recSVUMI_MAXi() { recVUMI_MAXi(VU, s_vuInfo); } +void recSVUMI_MAXx() { recVUMI_MAXx(VU, s_vuInfo); } +void recSVUMI_MAXy() { recVUMI_MAXy(VU, s_vuInfo); } +void recSVUMI_MAXz() { recVUMI_MAXz(VU, s_vuInfo); } +void recSVUMI_MAXw() { recVUMI_MAXw(VU, s_vuInfo); } + +void recSVUMI_MINI() { recVUMI_MINI(VU, s_vuInfo); } +void recSVUMI_MINIi() { recVUMI_MINIi(VU, s_vuInfo); } +void recSVUMI_MINIx() { recVUMI_MINIx(VU, s_vuInfo); } +void recSVUMI_MINIy() { recVUMI_MINIy(VU, s_vuInfo); } +void recSVUMI_MINIz() { recVUMI_MINIz(VU, s_vuInfo); } +void recSVUMI_MINIw() { recVUMI_MINIw(VU, s_vuInfo); } + +void recSVUMI_FTOI0() { recVUMI_FTOI0(VU, s_vuInfo); } +void recSVUMI_FTOI4() { recVUMI_FTOI4(VU, s_vuInfo); } +void recSVUMI_FTOI12() { recVUMI_FTOI12(VU, s_vuInfo); } +void recSVUMI_FTOI15() { recVUMI_FTOI15(VU, s_vuInfo); } +void recSVUMI_ITOF0() { recVUMI_ITOF0(VU, s_vuInfo); } +void recSVUMI_ITOF4() { recVUMI_ITOF4(VU, s_vuInfo); } +void recSVUMI_ITOF12() { recVUMI_ITOF12(VU, s_vuInfo); } +void recSVUMI_ITOF15() { recVUMI_ITOF15(VU, s_vuInfo); } + +void recSVUMI_OPMULA() { recVUMI_OPMULA(VU, s_vuInfo); } +void recSVUMI_OPMSUB() { recVUMI_OPMSUB(VU, s_vuInfo); } +void recSVUMI_NOP() { } +void recSVUMI_CLIP() { recVUMI_CLIP(VU, s_vuInfo); } + +// lower inst +void recSVUMI_MTIR() { recVUMI_MTIR(VU, s_vuInfo); } +void recSVUMI_MR32() { recVUMI_MR32(VU, s_vuInfo); } +void recSVUMI_MFIR() { recVUMI_MFIR(VU, s_vuInfo); } +void recSVUMI_MOVE() { recVUMI_MOVE(VU, s_vuInfo); } +void recSVUMI_WAITQ() { recVUMI_WAITQ(VU, s_vuInfo); } +void recSVUMI_MFP() { recVUMI_MFP(VU, s_vuInfo); } +void recSVUMI_WAITP() { recVUMI_WAITP(VU, s_vuInfo); } + +void recSVUMI_SQRT() { recVUMI_SQRT(VU, s_vuInfo); } +void recSVUMI_RSQRT() { recVUMI_RSQRT(VU, s_vuInfo); } +void recSVUMI_DIV() { recVUMI_DIV(VU, s_vuInfo); } + +void recSVUMI_ESADD() { recVUMI_ESADD(VU, s_vuInfo); } +void recSVUMI_ERSADD() { recVUMI_ERSADD(VU, s_vuInfo); } +void recSVUMI_ELENG() { recVUMI_ELENG(VU, s_vuInfo); } +void recSVUMI_ERLENG() { recVUMI_ERLENG(VU, s_vuInfo); } +void recSVUMI_EATANxy() { recVUMI_EATANxy(VU, s_vuInfo); } +void recSVUMI_EATANxz() { recVUMI_EATANxz(VU, s_vuInfo); } +void recSVUMI_ESUM() { recVUMI_ESUM(VU, s_vuInfo); } +void recSVUMI_ERCPR() { recVUMI_ERCPR(VU, s_vuInfo); } +void recSVUMI_ESQRT() { recVUMI_ESQRT(VU, s_vuInfo); } +void recSVUMI_ERSQRT() { recVUMI_ERSQRT(VU, s_vuInfo); } +void recSVUMI_ESIN() { recVUMI_ESIN(VU, s_vuInfo); } +void recSVUMI_EATAN() { recVUMI_EATAN(VU, s_vuInfo); } +void recSVUMI_EEXP() { recVUMI_EEXP(VU, s_vuInfo); } + +void recSVUMI_XITOP() { recVUMI_XITOP(VU, s_vuInfo); } +void recSVUMI_XGKICK() { recSVUMI_XGKICK(VU, s_vuInfo); } +void recSVUMI_XTOP() { recVUMI_XTOP(VU, s_vuInfo); } + +void recSVUMI_RINIT() { recVUMI_RINIT(VU, s_vuInfo); } +void recSVUMI_RGET() { recVUMI_RGET(VU, s_vuInfo); } +void recSVUMI_RNEXT() { recVUMI_RNEXT(VU, s_vuInfo); } +void recSVUMI_RXOR() { recVUMI_RXOR(VU, s_vuInfo); } + +void recSVUMI_FSAND() { recVUMI_FSAND(VU, s_vuInfo); } +void recSVUMI_FSEQ() { recVUMI_FSEQ(VU, s_vuInfo); } +void recSVUMI_FSOR() { recVUMI_FSOR(VU, s_vuInfo); } +void recSVUMI_FSSET() { recVUMI_FSSET(VU, s_vuInfo); } +void recSVUMI_FMEQ() { recVUMI_FMEQ(VU, s_vuInfo); } +void recSVUMI_FMOR() { recVUMI_FMOR(VU, s_vuInfo); } +void recSVUMI_FCEQ() { recVUMI_FCEQ(VU, s_vuInfo); } +void recSVUMI_FCOR() { recVUMI_FCOR(VU, s_vuInfo); } +void recSVUMI_FCSET() { recVUMI_FCSET(VU, s_vuInfo); } +void recSVUMI_FCGET() { recVUMI_FCGET(VU, s_vuInfo); } +void recSVUMI_FCAND() { recVUMI_FCAND(VU, s_vuInfo); } +void recSVUMI_FMAND() { recVUMI_FMAND(VU, s_vuInfo); } + +void recSVUMI_LQ() { recVUMI_LQ(VU, s_vuInfo); } +void recSVUMI_LQD() { recVUMI_LQD(VU, s_vuInfo); } +void recSVUMI_LQI() { recVUMI_LQI(VU, s_vuInfo); } +void recSVUMI_SQ() { recVUMI_SQ(VU, s_vuInfo); } +void recSVUMI_SQD() { recVUMI_SQD(VU, s_vuInfo); } +void recSVUMI_SQI() { recVUMI_SQI(VU, s_vuInfo); } +void recSVUMI_ILW() { recVUMI_ILW(VU, s_vuInfo); } +void recSVUMI_ISW() { recVUMI_ISW(VU, s_vuInfo); } +void recSVUMI_ILWR() { recVUMI_ILWR(VU, s_vuInfo); } +void recSVUMI_ISWR() { recVUMI_ISWR(VU, s_vuInfo); } + +void recSVUMI_IADD() { recVUMI_IADD(VU, s_vuInfo); } +void recSVUMI_IADDI() { recVUMI_IADDI(VU, s_vuInfo); } +void recSVUMI_IADDIU() { recVUMI_IADDIU(VU, s_vuInfo); } +void recSVUMI_IOR() { recVUMI_IOR(VU, s_vuInfo); } +void recSVUMI_ISUB() { recVUMI_ISUB(VU, s_vuInfo); } +void recSVUMI_IAND() { recVUMI_IAND(VU, s_vuInfo); } +void recSVUMI_ISUBIU() { recVUMI_ISUBIU(VU, s_vuInfo); } + +void recSVU_UPPER_FD_00( void ); +void recSVU_UPPER_FD_01( void ); +void recSVU_UPPER_FD_10( void ); +void recSVU_UPPER_FD_11( void ); +void recSVULowerOP( void ); +void recSVULowerOP_T3_00( void ); +void recSVULowerOP_T3_01( void ); +void recSVULowerOP_T3_10( void ); +void recSVULowerOP_T3_11( void ); +void recSVUunknown( void ); + +void (*recSVU_LOWER_OPCODE[128])() = { + recSVUMI_LQ , recSVUMI_SQ , recSVUunknown , recSVUunknown, + recSVUMI_ILW , recSVUMI_ISW , recSVUunknown , recSVUunknown, + recSVUMI_IADDIU, recSVUMI_ISUBIU, recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_FCEQ , recSVUMI_FCSET , recSVUMI_FCAND, recSVUMI_FCOR, /* 0x10 */ + recSVUMI_FSEQ , recSVUMI_FSSET , recSVUMI_FSAND, recSVUMI_FSOR, + recSVUMI_FMEQ , recSVUunknown , recSVUMI_FMAND, recSVUMI_FMOR, + recSVUMI_FCGET , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_B , recSVUMI_BAL , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUMI_JR , recSVUMI_JALR , recSVUunknown , recSVUunknown, + recSVUMI_IBEQ , recSVUMI_IBNE , recSVUunknown , recSVUunknown, + recSVUMI_IBLTZ , recSVUMI_IBGTZ , recSVUMI_IBLEZ, recSVUMI_IBGEZ, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x40*/ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x50 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x60 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x70 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, +}; + +void (*recSVULowerOP_T3_00_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MOVE , recSVUMI_LQI , recSVUMI_DIV , recSVUMI_MTIR, + recSVUMI_RNEXT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_MFP , recSVUMI_XTOP , recSVUMI_XGKICK, + recSVUMI_ESADD , recSVUMI_EATANxy, recSVUMI_ESQRT, recSVUMI_ESIN, +}; + +void (*recSVULowerOP_T3_01_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MR32 , recSVUMI_SQI , recSVUMI_SQRT , recSVUMI_MFIR, + recSVUMI_RGET , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUMI_XITOP, recSVUunknown, + recSVUMI_ERSADD, recSVUMI_EATANxz, recSVUMI_ERSQRT, recSVUMI_EATAN, +}; + +void (*recSVULowerOP_T3_10_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_LQD , recSVUMI_RSQRT, recSVUMI_ILWR, + recSVUMI_RINIT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ELENG , recSVUMI_ESUM , recSVUMI_ERCPR, recSVUMI_EEXP, +}; + +void (*recSVULowerOP_T3_11_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_SQD , recSVUMI_WAITQ, recSVUMI_ISWR, + recSVUMI_RXOR , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ERLENG, recSVUunknown , recSVUMI_WAITP, recSVUunknown, +}; + +void (*recSVULowerOP_OPCODE[64])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_IADD , recSVUMI_ISUB , recSVUMI_IADDI, recSVUunknown, /* 0x30 */ + recSVUMI_IAND , recSVUMI_IOR , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP_T3_00, recSVULowerOP_T3_01, recSVULowerOP_T3_10, recSVULowerOP_T3_11, +}; + +void (*recSVU_UPPER_OPCODE[64])() = { + recSVUMI_ADDx , recSVUMI_ADDy , recSVUMI_ADDz , recSVUMI_ADDw, + recSVUMI_SUBx , recSVUMI_SUBy , recSVUMI_SUBz , recSVUMI_SUBw, + recSVUMI_MADDx , recSVUMI_MADDy , recSVUMI_MADDz , recSVUMI_MADDw, + recSVUMI_MSUBx , recSVUMI_MSUBy , recSVUMI_MSUBz , recSVUMI_MSUBw, + recSVUMI_MAXx , recSVUMI_MAXy , recSVUMI_MAXz , recSVUMI_MAXw, /* 0x10 */ + recSVUMI_MINIx , recSVUMI_MINIy , recSVUMI_MINIz , recSVUMI_MINIw, + recSVUMI_MULx , recSVUMI_MULy , recSVUMI_MULz , recSVUMI_MULw, + recSVUMI_MULq , recSVUMI_MAXi , recSVUMI_MULi , recSVUMI_MINIi, + recSVUMI_ADDq , recSVUMI_MADDq , recSVUMI_ADDi , recSVUMI_MADDi, /* 0x20 */ + recSVUMI_SUBq , recSVUMI_MSUBq , recSVUMI_SUBi , recSVUMI_MSUBi, + recSVUMI_ADD , recSVUMI_MADD , recSVUMI_MUL , recSVUMI_MAX, + recSVUMI_SUB , recSVUMI_MSUB , recSVUMI_OPMSUB, recSVUMI_MINI, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVU_UPPER_FD_00, recSVU_UPPER_FD_01, recSVU_UPPER_FD_10, recSVU_UPPER_FD_11, +}; + +void (*recSVU_UPPER_FD_00_TABLE[32])() = { + recSVUMI_ADDAx, recSVUMI_SUBAx , recSVUMI_MADDAx, recSVUMI_MSUBAx, + recSVUMI_ITOF0, recSVUMI_FTOI0, recSVUMI_MULAx , recSVUMI_MULAq , + recSVUMI_ADDAq, recSVUMI_SUBAq, recSVUMI_ADDA , recSVUMI_SUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_01_TABLE[32])() = { + recSVUMI_ADDAy , recSVUMI_SUBAy , recSVUMI_MADDAy, recSVUMI_MSUBAy, + recSVUMI_ITOF4 , recSVUMI_FTOI4 , recSVUMI_MULAy , recSVUMI_ABS , + recSVUMI_MADDAq, recSVUMI_MSUBAq, recSVUMI_MADDA , recSVUMI_MSUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_10_TABLE[32])() = { + recSVUMI_ADDAz , recSVUMI_SUBAz , recSVUMI_MADDAz, recSVUMI_MSUBAz, + recSVUMI_ITOF12, recSVUMI_FTOI12, recSVUMI_MULAz , recSVUMI_MULAi , + recSVUMI_MADDAi, recSVUMI_SUBAi , recSVUMI_MULA , recSVUMI_OPMULA, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_11_TABLE[32])() = { + recSVUMI_ADDAw , recSVUMI_SUBAw , recSVUMI_MADDAw, recSVUMI_MSUBAw, + recSVUMI_ITOF15, recSVUMI_FTOI15, recSVUMI_MULAw , recSVUMI_CLIP , + recSVUMI_MADDAi, recSVUMI_MSUBAi, recSVUunknown , recSVUMI_NOP , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void recSVU_UPPER_FD_00( void ) +{ + recSVU_UPPER_FD_00_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_01( void ) +{ + recSVU_UPPER_FD_01_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_10( void ) +{ + recSVU_UPPER_FD_10_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_11( void ) +{ + recSVU_UPPER_FD_11_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP( void ) +{ + recSVULowerOP_OPCODE[ VU->code & 0x3f ]( ); +} + +void recSVULowerOP_T3_00( void ) +{ + recSVULowerOP_T3_00_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_01( void ) +{ + recSVULowerOP_T3_01_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_10( void ) +{ + recSVULowerOP_T3_10_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_11( void ) +{ + recSVULowerOP_T3_11_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVUunknown( void ) +{ + SysPrintf("Unknown SVU micromode opcode called\n"); +} diff --git a/x86/iVUzerorec.h b/x86/iVUzerorec.h new file mode 100644 index 0000000000..15922522b4 --- /dev/null +++ b/x86/iVUzerorec.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#ifndef VU1_SUPER_RECOMPILER +#define VU1_SUPER_RECOMPILER + +#ifdef __cplusplus +extern "C" { +#endif + +void SuperVUInit(int vuindex); // if vuindex is -1, inits the global VU resources +void SuperVUDestroy(int vuindex); // if vuindex is -1, destroys everything +void SuperVUReset(int vuindex); // if vuindex is -1, resets everything + +void SuperVUExecuteProgram(u32 startpc, int vuindex); +void SuperVUClear(u32 startpc, u32 size, int vuindex); + +u32 SuperVUGetRecTimes(int clear); + +// read = 0, will write to reg +// read = 1, will read from reg +// read = 2, addr of previously written reg (used for status and clip flags) +u32 SuperVUGetVIAddr(int reg, int read); + +// if p == 0, flush q else flush p; if wait is != 0, waits for p/q +void SuperVUFlush(int p, int wait); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/x86/ir5900tables.c b/x86/ir5900tables.c new file mode 100644 index 0000000000..293abe75e8 --- /dev/null +++ b/x86/ir5900tables.c @@ -0,0 +1,1362 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Holds instruction tables for the r5900 recompiler + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" + +//////////////////////////////////////////////////// +static void recNULL( void ) +{ + SysPrintf("EE: Unimplemented op %x\n", cpuRegs.code); +} + +//////////////////////////////////////////////////// +static void recREGIMM( void ) +{ + recREG[ _Rt_ ]( ); +} + +//////////////////////////////////////////////////// +static void recSPECIAL( void ) +{ + recSPC[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0( void ) +{ + recCP0[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0BC0( void ) +{ + recCP0BC0[ ( cpuRegs.code >> 16 ) & 0x03 ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0C0( void ) +{ + recCP0C0[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP1( void ) { + recCP1[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recMMI( void ) +{ + recMMIt[ _Funct_ ]( ); +} + + +/********************************************************** +* UNHANDLED YET OPCODES +* +**********************************************************/ + +//////////////////////////////////////////////////// +//REC_SYS(PREF); +//////////////////////////////////////////////////// +//REC_SYS(MFSA); +//////////////////////////////////////////////////// +//REC_SYS(MTSA); +//////////////////////////////////////////////////// +REC_SYS(TGE); +//////////////////////////////////////////////////// +REC_SYS(TGEU); +//////////////////////////////////////////////////// +REC_SYS(TLT); +//////////////////////////////////////////////////// +REC_SYS(TLTU); +//////////////////////////////////////////////////// +REC_SYS(TEQ); +//////////////////////////////////////////////////// +REC_SYS(TNE); +//////////////////////////////////////////////////// +REC_SYS(TGEI); +//////////////////////////////////////////////////// +REC_SYS(TGEIU); +//////////////////////////////////////////////////// +REC_SYS(TLTI); +//////////////////////////////////////////////////// +REC_SYS(TLTIU); +//////////////////////////////////////////////////// +REC_SYS(TEQI); +//////////////////////////////////////////////////// +REC_SYS(TNEI); +//////////////////////////////////////////////////// +//REC_SYS(MTSAB); +//////////////////////////////////////////////////// +//REC_SYS(MTSAH); + + +//////////////////////////////////////////////////// +static void recCACHE( void ) { +// MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (u32)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (u32)CACHE ); +// //branch = 2; +// +// CMP32ItoM((int)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// RET(); +// x86SetJ8(j8Ptr[0]); +} + + +static void recPREF( void ) +{ +} + + + +//////////////////////////////////////////////////// +static void recSYNC( void ) +{ +} + +static void recMFSA( void ) +{ + int mmreg; + if (!_Rd_) return; + + mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + if( mmreg >= 0 ) { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.sa); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.sa); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + _deleteEEreg(_Rd_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + } +} + +static void recMTSA( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] ); + } + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.sa, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&cpuRegs.sa, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } + } +} + +/* +void recTGE( void ) +{ +} + +void recTGEU( void ) +{ +} + +void recTLT( void ) +{ +} + +void recTLTU( void ) +{ +} + +void recTEQ( void ) +{ +} + +void recTNE( void ) +{ +} + +void recTGEI( void ) +{ +} + +void recTGEIU( void ) +{ +} + +void recTLTI( void ) +{ +} + +void recTLTIU( void ) +{ +} + +void recTEQI( void ) +{ +} + +void recTNEI( void ) +{ +} + +*/ +static void recMTSAB( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0xF); + MOV32ItoR(ECX, _Imm_); + AND32ItoR(ECX, 0xF); + XOR32RtoR(EAX, ECX); + SHL32ItoR(EAX, 3); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +static void recMTSAH( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0x7); + MOV32ItoR(ECX, _Imm_); + AND32ItoR(ECX, 0x7); + XOR32RtoR(EAX, ECX); + SHL32ItoR(EAX, 4); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +///////////////////////////////// +// Foward-Prob Function Tables // +///////////////////////////////// +extern void recCOP2( void ); +extern void recSYSCALL( void ); +extern void recBREAK( void ); + +void (*recBSC[64] )() = { + recSPECIAL, recREGIMM, recJ, recJAL, recBEQ, recBNE, recBLEZ, recBGTZ, + recADDI, recADDIU, recSLTI, recSLTIU, recANDI, recORI, recXORI, recLUI, + recCOP0, recCOP1, recCOP2, recNULL, recBEQL, recBNEL, recBLEZL, recBGTZL, + recDADDI, recDADDIU, recLDL, recLDR, recMMI, recNULL, recLQ, recSQ, + recLB, recLH, recLWL, recLW, recLBU, recLHU, recLWR, recLWU, + recSB, recSH, recSWL, recSW, recSDL, recSDR, recSWR, recCACHE, + recNULL, recLWC1, recNULL, recPREF, recNULL, recNULL, recLQC2, recLD, + recNULL, recSWC1, recNULL, recNULL, recNULL, recNULL, recSQC2, recSD +}; + +#ifdef WIN32_VIRTUAL_MEM +// coissued insts +void (*recBSC_co[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recLDL_co, recLDR_co, recNULL, recNULL, recLQ_co, recSQ_co, + recLB_co, recLH_co, recLWL_co, recLW_co, recLBU_co, recLHU_co, recLWR_co, recLWU_co, + recSB_co, recSH_co, recSWL_co, recSW_co, recSDL_co, recSDR_co, recSWR_co, recNULL, + recNULL, recLWC1_co, recNULL, recNULL, recNULL, recNULL, recLQC2_co, recLD_co, + recNULL, recSWC1_co, recNULL, recNULL, recNULL, recNULL, recSQC2_co, recSD_co +}; +#endif + +void (*recSPC[64] )() = { + recSLL, recNULL, recSRL, recSRA, recSLLV, recNULL, recSRLV, recSRAV, + recJR, recJALR, recMOVZ, recMOVN, recSYSCALL, recBREAK, recNULL, recSYNC, + recMFHI, recMTHI, recMFLO, recMTLO, recDSLLV, recNULL, recDSRLV, recDSRAV, + recMULT, recMULTU, recDIV, recDIVU, recNULL, recNULL, recNULL, recNULL, + recADD, recADDU, recSUB, recSUBU, recAND, recOR, recXOR, recNOR, + recMFSA, recMTSA, recSLT, recSLTU, recDADD, recDADDU, recDSUB, recDSUBU, + recTGE, recTGEU, recTLT, recTLTU, recTEQ, recNULL, recTNE, recNULL, + recDSLL, recNULL, recDSRL, recDSRA, recDSLL32, recNULL, recDSRL32, recDSRA32 +}; + +void (*recREG[32] )() = { + recBLTZ, recBGEZ, recBLTZL, recBGEZL, recNULL, recNULL, recNULL, recNULL, + recTGEI, recTGEIU, recTLTI, recTLTIU, recTEQI, recNULL, recTNEI, recNULL, + recBLTZAL, recBGEZAL, recBLTZALL, recBGEZALL, recNULL, recNULL, recNULL, recNULL, + recMTSAB, recMTSAH, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0[32] )() = { + recMFC0, recNULL, recNULL, recNULL, recMTC0, recNULL, recNULL, recNULL, + recCOP0BC0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP0C0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0BC0[32] )() = { + recBC0F, recBC0T, recBC0FL, recBC0TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0C0[64] )() = { + recNULL, recTLBR, recTLBWI, recNULL, recNULL, recNULL, recTLBWR, recNULL, + recTLBP, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recERET, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recEI, recDI, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1[32] )() = { + recMFC1, recNULL, recCFC1, recNULL, recMTC1, recNULL, recCTC1, recNULL, + recCOP1_BC1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP1_S, recNULL, recNULL, recNULL, recCOP1_W, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1BC1[32] )() = { + recBC1F, recBC1T, recBC1FL, recBC1TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1S[64] )() = { + recADD_S, recSUB_S, recMUL_S, recDIV_S, recSQRT_S, recABS_S, recMOV_S, recNEG_S, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recRSQRT_S, recNULL, + recADDA_S, recSUBA_S, recMULA_S, recNULL, recMADD_S, recMSUB_S, recMADDA_S, recMSUBA_S, + recNULL, recNULL, recNULL, recNULL, recCVT_W, recNULL, recNULL, recNULL, + recMAX_S, recMIN_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recC_F, recNULL, recC_EQ, recNULL, recC_LT, recNULL, recC_LE, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1W[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCVT_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMIt[64] )() = { + recMADD, recMADDU, recNULL, recNULL, recPLZCW, recNULL, recNULL, recNULL, + recMMI0, recMMI2, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMFHI1, recMTHI1, recMFLO1, recMTLO1, recNULL, recNULL, recNULL, recNULL, + recMULT1, recMULTU1, recDIV1, recDIVU1, recNULL, recNULL, recNULL, recNULL, + recMADD1, recMADDU1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMMI1 , recMMI3, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recPMFHL, recPMTHL, recNULL, recNULL, recPSLLH, recNULL, recPSRLH, recPSRAH, + recNULL, recNULL, recNULL, recNULL, recPSLLW, recNULL, recPSRLW, recPSRAW, +}; + +void (*recMMI0t[32] )() = { + recPADDW, recPSUBW, recPCGTW, recPMAXW, + recPADDH, recPSUBH, recPCGTH, recPMAXH, + recPADDB, recPSUBB, recPCGTB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDSW, recPSUBSW, recPEXTLW, recPPACW, + recPADDSH, recPSUBSH, recPEXTLH, recPPACH, + recPADDSB, recPSUBSB, recPEXTLB, recPPACB, + recNULL, recNULL, recPEXT5, recPPAC5, +}; + +void (*recMMI1t[32] )() = { + recNULL, recPABSW, recPCEQW, recPMINW, + recPADSBH, recPABSH, recPCEQH, recPMINH, + recNULL, recNULL, recPCEQB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDUW, recPSUBUW, recPEXTUW, recNULL, + recPADDUH, recPSUBUH, recPEXTUH, recNULL, + recPADDUB, recPSUBUB, recPEXTUB, recQFSRV, + recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMI2t[32] )() = { + recPMADDW, recNULL, recPSLLVW, recPSRLVW, + recPMSUBW, recNULL, recNULL, recNULL, + recPMFHI, recPMFLO, recPINTH, recNULL, + recPMULTW, recPDIVW, recPCPYLD, recNULL, + recPMADDH, recPHMADH, recPAND, recPXOR, + recPMSUBH, recPHMSBH, recNULL, recNULL, + recNULL, recNULL, recPEXEH, recPREVH, + recPMULTH, recPDIVBW, recPEXEW, recPROT3W, +}; + +void (*recMMI3t[32] )() = { + recPMADDUW, recNULL, recNULL, recPSRAVW, + recNULL, recNULL, recNULL, recNULL, + recPMTHI, recPMTLO, recPINTEH, recNULL, + recPMULTUW, recPDIVUW, recPCPYUD, recNULL, + recNULL, recNULL, recPOR, recPNOR, + recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recPEXCH, recPCPYH, + recNULL, recNULL, recPEXCW, recNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpropSetRead(reg, mask) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpropSetWrite0(reg, mask, live) { \ + prev->regs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +#define rpropSetWrite(reg, mask) { \ + rpropSetWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +#define rpropSetFast(write1, read1, read2, mask) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ +} \ + +#define rpropSetLOHI(write1, read1, read2, mask, lo, hi) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( (lo) & MODE_WRITE ) { rpropSetWrite(XMMGPR_LO, mask); } \ + if( (hi) & MODE_WRITE ) { rpropSetWrite(XMMGPR_HI, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ + if( (lo) & MODE_READ ) { rpropSetRead(XMMGPR_LO, mask); } \ + if( (hi) & MODE_READ ) { rpropSetRead(XMMGPR_HI, mask); } \ +} \ + +// FPU regs +#define rpropSetFPURead(reg, mask) { \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + prev->fpuregs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 0); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 0); \ +} \ + +#define rpropSetFPUWrite0(reg, mask, live) { \ + prev->fpuregs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + prev->fpuregs[reg] |= EEINST_USED; \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 1); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 1); \ +} + +#define rpropSetFPUWrite(reg, mask) { \ + rpropSetFPUWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +void rpropBSC(EEINST* prev, EEINST* pinst); +void rpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpropREGIMM(EEINST* prev, EEINST* pinst); +void rpropCP0(EEINST* prev, EEINST* pinst); +void rpropCP1(EEINST* prev, EEINST* pinst); +void rpropCP2(EEINST* prev, EEINST* pinst); +void rpropMMI(EEINST* prev, EEINST* pinst); +void rpropMMI0(EEINST* prev, EEINST* pinst); +void rpropMMI1(EEINST* prev, EEINST* pinst); +void rpropMMI2(EEINST* prev, EEINST* pinst); +void rpropMMI3(EEINST* prev, EEINST* pinst); + +//SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, +//ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, +//COP0, COP1, COP2, NULL, BEQL, BNEL, BLEZL, BGTZL, +//DADDI, DADDIU, LDL, LDR, MMI, NULL, LQ, SQ, +//LB, LH, LWL, LW, LBU, LHU, LWR, LWU, +//SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, +//NULL, LWC1, NULL, PREF, NULL, NULL, LQC2, LD, +//NULL, SWC1, NULL, NULL, NULL, NULL, SQC2, SD +void rpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(cpuRegs.code >> 26) { + case 0: rpropSPECIAL(prev, pinst); break; + case 1: rpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpropSetWrite(31, EEINST_LIVE1); + break; + case 4: // beq + case 5: // bne + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_XMM|EEINST_MMX):0); + break; + + case 20: // beql + case 21: // bnel + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_XMM|EEINST_MMX):0); + break; + + case 6: // blez + case 7: // bgtz + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 22: // blezl + case 23: // bgtzl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // daddi + case 25: // daddiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|((_Rs_!=0&&cpucaps.hasStreamingSIMD2Extensions)?EEINST_MMX:0)); + break; + + case 8: // addi + case 9: // addiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + break; + + case 10: // slti + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + case 11: // sltiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 12: // andi + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, (_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 13: // ori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 14: // xori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 15: // lui + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 16: rpropCP0(prev, pinst); break; + case 17: rpropCP1(prev, pinst); break; + case 18: rpropCP2(prev, pinst); break; + + // loads + case 34: // lwl + case 38: // lwr + case 26: // ldl + case 27: // ldr + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 28: rpropMMI(prev, pinst); break; + + case 30: // lq + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + case 31: // sq + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + rpropSetRead(_Rt_, 0); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + case 44: // sdl + case 45: // sdr + case 63: // sd + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX|EEINST_XMM); + rpropSetRead(_Rs_, 0); + break; + + case 49: // lwc1 + rpropSetFPUWrite(_Rt_, EEINST_XMM); + rpropSetRead(_Rs_, 0); + break; + + case 57: // swc1 + rpropSetFPURead(_Rt_, EEINST_XMM); + rpropSetRead(_Rs_, 0); + break; + + case 54: // lqc2 + case 62: // sqc2 + rpropSetRead(_Rs_, 0); + break; + + default: + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=0?EEINST_MMX:0)); + break; + } +} + +//SLL, NULL, SRL, SRA, SLLV, NULL, SRLV, SRAV, +//JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, NULL, SYNC, +//MFHI, MTHI, MFLO, MTLO, DSLLV, NULL, DSRLV, DSRAV, +//MULT, MULTU, DIV, DIVU, NULL, NULL, NULL, NULL, +//ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, +//MFSA, MTSA, SLT, SLTU, DADD, DADDU, DSUB, DSUBU, +//TGE, TGEU, TLT, TLTU, TEQ, NULL, TNE, NULL, +//DSLL, NULL, DSRL, DSRA, DSLL32, NULL, DSRL32, DSRA32 +void rpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 4: // sllv + case 6: // srlv + case 7: // srav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 8: // JR + rpropSetRead(_Rs_, 0); + break; + case 9: // JALR + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 10: // movz + case 11: // movn + // do not write _Rd_! + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rd_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + _recFillRegister(pinst, XMMTYPE_GPRREG, _Rd_, 1); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_XMM)|EEINST_LIVE1); + break; + case 17: // mthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_XMM)|EEINST_LIVE1); + break; + case 19: // mtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 20: // dsllv + case 22: // dsrlv + case 23: // dsrav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + + case 24: // mult + // can do unsigned mult only if HI isn't used + //temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE0|EEINST_LIVE1))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + temp = 0; + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 26: // div + case 27: // divu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_XMM|EEINST_MMX; + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ ) rpropSetRead(_Rs_, 0); + if( _Rt_ ) rpropSetRead(_Rt_, 0); + pinst->info |= EEINST_MMX; + break; + + case 36: // and + case 37: // or + case 38: // xor + case 39: // nor + // if rd == rs or rt, keep live1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + break; + + case 40: // mfsa + rpropSetWrite(_Rd_, EEINST_LIVE1); + break; + case 41: // mtsa + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + break; + + case 42: // slt + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 43: // sltu + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 44: // dadd + case 45: // daddu + case 46: // dsub + case 47: // dsubu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ == 0 || _Rt_ == 0 ) { + // just a copy, so don't force mmx + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + } + else { + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + } + pinst->info |= EEINST_MMX; + break; + + // traps + case 48: case 49: case 50: case 51: case 52: case 54: + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + break; + + case 56: // dsll + case 58: // dsrl + case 59: // dsra + case 62: // dsrl32 + case 63: // dsra32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 60: // dsll32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + default: + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + } +} + +//BLTZ, BGEZ, BLTZL, BGEZL, NULL, NULL, NULL, NULL, +//TGEI, TGEIU, TLTI, TLTIU, TEQI, NULL, TNEI, NULL, +//BLTZAL, BGEZAL, BLTZALL, BGEZALL, NULL, NULL, NULL, NULL, +//MTSAB, MTSAH, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + case 2: // bltzl + case 3: // bgezl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + // traps + case 8: + case 9: + case 10: + case 11: + case 12: + case 14: + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 18: // bltzall + case 19: // bgezall + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mtsab + case 25: // mtsah + rpropSetRead(_Rs_, 0); + break; + default: + assert(0); + break; + } +} + +//MFC0, NULL, NULL, NULL, MTC0, NULL, NULL, NULL, +//COP0BC0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//COP0C0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 4: + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 8: // cop0bc0 + _recClearInst(prev); + prev->info = 0; + break; + case 16: // cop0c0 + _recClearInst(prev); + prev->info = 0; + break; + } +} + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +//ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, RSQRT_S, NULL, +//ADDA_S, SUBA_S, MULA_S, NULL, MADD_S, MSUB_S, MADDA_S, MSUBA_S, +//NULL, NULL, NULL, NULL, CVT_W, NULL, NULL, NULL, +//MAX_S, MIN_S, NULL, NULL, NULL, NULL, NULL, NULL, +//C_F, NULL, C_EQ, NULL, C_LT, NULL, C_LE, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP1(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + break; + case 2: // cfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_XMM|EEINST_MMX); + break; + case 4: // mtc1 + rpropSetFPUWrite(_Fs_, EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 6: // ctc1 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM|EEINST_MMX); + break; + case 8: // bc1 + break; + case 16: + // floating point ops + pinst->info |= EEINST_XMM; + switch( _Funct_ ) { + case 0: // add.s + case 1: // sub.s + case 2: // mul.s + case 3: // div.s + case 22: // rsqrt.s + case 40: // max.s + case 41: // min.s + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + case 4: // sqrt.s + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + case 5: // abs.s + case 6: // mov.s + case 7: // neg.s + case 36: // cvt.w + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + break; + case 24: // adda.s + case 25: // suba.s + case 26: // mula.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + case 28: // madd.s + case 29: // msub.s + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + + case 30: // madda.s + case 31: // msuba.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + + case 48: // c.f + case 50: // c.eq + case 52: // c.lt + case 54: // c.le + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + default: assert(0); + } + break; + case 20: + assert( _Funct_ == 32 ); // CVT.S.W + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + break; + default: + assert(0); + } +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +void rpropCP2(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 1: // qmfc2 + rpropSetWrite(_Rt_, EEINST_LIVE2|EEINST_LIVE1); + break; + + case 2: // cfc2 + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 5: // qmtc2 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 6: // ctc2 + rpropSetRead(_Rt_, 0); + break; + + case 8: // bc2 + break; + + default: + // vu macro mode insts + pinst->info |= 2; + break; + } +} + +//MADD, MADDU, NULL, NULL, PLZCW, NULL, NULL, NULL, +//MMI0, MMI2, NULL, NULL, NULL, NULL, NULL, NULL, +//MFHI1, MTHI1, MFLO1, MTLO1, NULL, NULL, NULL, NULL, +//MULT1, MULTU1, DIV1, DIVU1, NULL, NULL, NULL, NULL, +//MADD1, MADDU1, NULL, NULL, NULL, NULL, NULL, NULL, +//MMI1 , MMI3, NULL, NULL, NULL, NULL, NULL, NULL, +//PMFHL, PMTHL, NULL, NULL, PSLLH, NULL, PSRLH, PSRAH, +//NULL, NULL, NULL, NULL, PSLLW, NULL, PSRLW, PSRAW, +void rpropMMI(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(cpuRegs.code&0x3f) { + case 0: // madd + case 1: // maddu + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 4: // plzcw + rpropSetFast(_Rd_, _Rs_, 0, EEINST_LIVE1); + break; + case 8: rpropMMI0(prev, pinst); break; + case 9: rpropMMI2(prev, pinst); break; + + case 16: // mfhi1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_XMM))?EEINST_MMX:EEINST_XMM); + rpropSetRead(XMMGPR_HI, temp|EEINST_LIVE2); + break; + case 17: // mthi1 + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_XMM))?EEINST_MMX:EEINST_XMM); + rpropSetRead(XMMGPR_LO, temp|EEINST_LIVE2); + break; + case 19: // mtlo1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mult1 + temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE2))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 26: // div1 + case 27: // divu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_XMM|EEINST_MMX; + break; + + case 32: // madd1 + case 33: // maddu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2); + break; + + case 40: rpropMMI1(prev, pinst); break; + case 41: rpropMMI3(prev, pinst); break; + + case 48: // pmfhl + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + case 49: // pmthl + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +//recPADDW, PSUBW, PCGTW, PMAXW, +//PADDH, PSUBH, PCGTH, PMAXH, +//PADDB, PSUBB, PCGTB, NULL, +//NULL, NULL, NULL, NULL, +//PADDSW, PSUBSW, PEXTLW, PPACW, +//PADDSH, PSUBSH, PEXTLH, PPACH, +//PADDSB, PSUBSB, PEXTLB, PPACB, +//NULL, NULL, PEXT5, PPAC5, +void rpropMMI0(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 16: // paddsw + case 17: // psubsw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextlw + case 22: // pextlh + case 26: // pextlb + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + + case 30: // pext5 + case 31: // ppac5 + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +void rpropMMI1(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 1: // pabsw + case 5: // pabsh + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + case 17: // psubuw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextuw + case 22: // pextuh + case 26: // pextub + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_XMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +void rpropMMI2(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmaddw + case 4: // pmsubw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 2: // psllvw + case 3: // psllvw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + case 8: // pmfhi + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 9: // pmflo + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 10: // pinth + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 12: // pmultw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyld + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 16: // pmaddh + case 17: // phmadh + case 20: // pmsubh + case 21: // phmsbh + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + + case 26: // pexeh + case 27: // prevh + case 30: // pexew + case 31: // prot3w + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + case 28: // pmulth + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_WRITE, MODE_WRITE); + break; + case 29: // pdivbw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +void rpropMMI3(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmadduw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 3: // psravw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + + case 8: // pmthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 9: // pmtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 12: // pmultuw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivuw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyud + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_XMM); + break; + + case 26: // pexch + case 27: // pcpyh + case 30: // pexcw + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} diff --git a/x86/ix86/ix86.c b/x86/ix86/ix86.c new file mode 100644 index 0000000000..4cde9253a4 --- /dev/null +++ b/x86/ix86/ix86.c @@ -0,0 +1,3086 @@ +/* + * ix86 core v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + */ + +#include +#include +#include +#include "ix86.h" + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +extern void SysPrintf(char *fmt, ...); + +// This function is just for rec debugging purposes +void CheckX86Ptr( void ) +{ +} + +void write64( u64 val ) +{ +#ifdef _DEBUG + CheckX86Ptr( ); +#endif + + *(u64*)x86Ptr = val; + x86Ptr += 8; +} + +void Rex( int w, int r, int x, int b ) +{ + assert(0); + write8( 0x40 | (w << 3) | (r << 2) | (x << 1) | (b) ); +} + +void ModRM( int mod, int rm, int reg ) +{ + write8( ( mod << 6 ) | ( (rm & 7) << 3 ) | ( reg & 7 ) ); +} + +void SibSB( int ss, int rm, int index ) +{ + write8( ( ss << 6 ) | ( rm << 3 ) | ( index ) ); +} + +void SET8R( int cc, int to ) +{ + write8( 0x0F ); + write8( cc ); + write8( 0xC0 | ( to ) ); +} + +u8* J8Rel( int cc, int to ) +{ + write8( cc ); + write8( to ); + return x86Ptr - 1; +} + +u16* J16Rel( int cc, u32 to ) +{ + write16( 0x0F66 ); + write8( cc ); + write16( to ); + return (u16*)( x86Ptr - 2 ); +} + +u32* J32Rel( int cc, u32 to ) +{ + write8( 0x0F ); + write8( cc ); + write32( to ); + return (u32*)( x86Ptr - 4 ); +} + +void CMOV32RtoR( int cc, int to, int from ) +{ + write8( 0x0F ); + write8( cc ); + ModRM( 3, to, from ); +} + +void CMOV32MtoR( int cc, int to, u32 from ) +{ + write8( 0x0F ); + write8( cc ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////////////////////// +void x86SetPtr( char* ptr ) +{ + x86Ptr = ptr; +} + +//////////////////////////////////////////////////// +void x86Shutdown( void ) +{ +} + +//////////////////////////////////////////////////// +void x86SetJ8( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + + if( ((u32)x86Ptr&0xf) > 4 ) { + + u32 newjump = jump + 16-((u32)x86Ptr&0xf); + + if( newjump <= 0x7f ) { + jump = newjump; + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + } + *j8 = (u8)jump; +} + +void x86SetJ16( u16 *j16 ) +{ + // doesn't work + u32 jump = ( x86Ptr - (s8*)j16 ) - 2; + + if ( jump > 0x7fff ) { + assert(0); + SysPrintf( "j16 greater than 0x7fff!!\n" ); + } + *j16 = (u16)jump; +} + +void x86SetJ16A( u16 *j16 ) +{ + if( ((u32)x86Ptr&0xf) > 4 ) { + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + x86SetJ16(j16); +} + +//////////////////////////////////////////////////// +void x86SetJ32( u32* j32 ) +{ + *j32 = ( x86Ptr - (s8*)j32 ) - 4; +} + +void x86SetJ32A( u32* j32 ) +{ + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + x86SetJ32(j32); +} + +//////////////////////////////////////////////////// +void x86Align( int bytes ) +{ + // fordward align + x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) ); +} + +/********************/ +/* IX86 intructions */ +/********************/ + +void STC( void ) +{ + write8( 0xF9 ); +} + +void CLC( void ) +{ + write8( 0xF8 ); +} + +//////////////////////////////////// +// mov instructions / +//////////////////////////////////// + +/* mov r64 to r64 */ +void MOV64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r64 to m64 */ +void MOV64RtoM( u64 to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, 0); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( (u32)MEMADDR(to, 4) ); +} + +/* mov m64 to r64 */ +void MOV64MtoR( x86IntRegType to, u64 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( (u32)MEMADDR(from, 4) ); +} + +/* mov imm32 to m64 */ +void MOV64ItoM(u32 to, u32 from ) +{ + Rex(1, 0, 0, 0); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* mov imm32 to r64 */ +void MOV32Ito64R( x86IntRegType to, s32 from ) +{ + Rex(1, 0, 0, to >> 3); + write8( 0xC7 ); + ModRM( 0, 0, to ); + write32( from ); +} + +/* mov imm64 to r64 */ +void MOV64ItoR( x86IntRegType to, u64 from ) { + Rex(1, 0, 0, to >> 3); + write8( 0xB8 | (to & 0x7) ); + write64( from ); +} + +/* mov [r64] to r64 */ +void MOV64RmtoR( x86IntRegType to, x86IntRegType from ) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x8B ); + ModRM( 0, to, from ); +} + +/* mov [r64][r64*scale] to r64 */ +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov r64 to [r64] */ +void MOV64RtoRm( x86IntRegType to, x86IntRegType from ) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov r64 to [r64][r64*scale] */ +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + + +/* mov r32 to r32 */ +void MOV32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r32 to m32 */ +void MOV32RtoM( u32 to, x86IntRegType from ) +{ + if (from > 7) { + Rex(0, from >> 3, 0, 0); + } + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m32 to r32 */ +void MOV32MtoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, to >> 3, 0, 0); + } + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r32 */ +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) { + if (from > 7 || to > 7) { + Rex(0, to >> 3, 0, from >> 3); + } + if (from == ESP) { + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + write8( 0x8B ); + ModRM( 0, to, from ); + } +} + +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ) { + if (from > 7 || to > 7) { + Rex(0, to >> 3, 0, from >> 3); + } + + write8( 0x8B ); + + if( offset == 0 ) { + if (from == ESP) { + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 0, to, from ); + } + } + else if( offset < 128 ) { + if (from == ESP) { + ModRM( 1, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 1, to, from ); + } + write8(offset); + } + else { + if (from == ESP) { + ModRM( 2, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 2, to, from ); + } + write32(offset); + } +} + +/* mov [r32][r32*scale] to r32 */ +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +/* mov r32 to [r32] */ +void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) { + if (from > 7 || to > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + if (to == ESP) { + write8( 0x89 ); + ModRM( 0, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + write8( 0x89 ); + ModRM( 0, from, to ); + } +} + +/* mov r32 to [r32][r32*scale] */ +void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov imm32 to r32 */ +void MOV32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xB8 | (to & 0x7) ); + write32( from ); +} + +/* mov imm32 to m32 */ +void MOV32ItoM(u32 to, u32 from ) +{ + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +// mov imm32 to [r32+off] +void MOV32ItoRmOffset( x86IntRegType to, u32 from, u32 offset) +{ + write8( 0xC7 ); + + if( to == ESP ) { + + if( offset == 0 ) { + ModRM( 0, 0, 4 ); + ModRM( 0, ESP, 4 ); + } + else if( offset < 128 ) { + ModRM( 1, 0, 4 ); + ModRM( 0, ESP, 4 ); + write8(offset); + } + else { + ModRM( 2, 0, 4 ); + ModRM( 0, ESP, 4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, 0, to ); + } + else if( offset < 128 ) { + ModRM( 1, 0, to ); + write8(offset); + } + else { + ModRM( 2, 0, to ); + write32(offset); + } + } + + write32(from); +} + +// mov r32 to [r32+off] +void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8( 0x89 ); + + if (to == ESP) { + if( offset == 0 ) { + ModRM( 0, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + else if( offset < 128 ) { + ModRM( 1, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write8(offset); + } + else { + ModRM( 2, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + } + else { + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } + } +} + +/* mov r16 to m16 */ +void MOV16RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m16 to r16 */ +void MOV16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOV16RmtoR( x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 0, to, from ); +} + +void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 2, to, from ); + write32( offset ); +} + +void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write16( 0x8B66 ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +void MOV16RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov imm16 to m16 */ +void MOV16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* mov r16 to [r32][r32*scale] */ +void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV16ItoR( x86IntRegType to, u16 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write16( 0xB866 | ((to & 0x7)<<8) ); + write16( from ); +} + +// mov imm16 to [r16+off] +void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset) +{ + assert( to != ESP ); + write16( 0xC766 ); + ModRM( 2, 0, to ); + write32(offset); + write16(from); +} + +// mov r16 to [r16+off] +void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + assert( to != ESP ); + write16( 0x8966 ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* mov r8 to m8 */ +void MOV8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x88 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m8 to r8 */ +void MOV8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x8A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r8 */ +void MOV8RmtoR(x86IntRegType to, x86IntRegType from) +{ + write8( 0x8A ); + ModRM( 0, to, from ); +} + +void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8( 0x8A ); + ModRM( 2, to, from ); + write32(offset); +} + +void MOV8RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x88 ); + ModRM( 0, from, to ); +} + +/* mov imm8 to m8 */ +void MOV8ItoM( u32 to, u8 from ) +{ + write8( 0xC6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +// mov imm8 to r8 +void MOV8ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xB0 | (to & 0x7) ); + write8( from ); +} + +// mov imm8 to [r8+off] +void MOV8ItoRmOffset( x86IntRegType to, u8 from, u32 offset) +{ + assert( to != ESP ); + write8( 0xC6 ); + ModRM( 2, 0, to ); + write32(offset); + write8(from); +} + +// mov r8 to [r8+off] +void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + assert( to != ESP ); + write8( 0x88 ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movsx r8 to r32 */ +void MOVSX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBE0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBE0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xBE0F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movsx m8 to r32 */ +void MOVSX32M8toR( x86IntRegType to, u32 from ) +{ + write16( 0xBE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movsx r16 to r32 */ +void MOVSX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBF0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBF0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xBF0F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movsx m16 to r32 */ +void MOVSX32M16toR( x86IntRegType to, u32 from ) +{ + write16( 0xBF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movzx r8 to r32 */ +void MOVZX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB60F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB60F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xB60F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movzx m8 to r32 */ +void MOVZX32M8toR( x86IntRegType to, u32 from ) +{ + write16( 0xB60F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movzx r16 to r32 */ +void MOVZX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB70F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB70F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xB70F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movzx m16 to r32 */ +void MOVZX32M16toR( x86IntRegType to, u32 from ) +{ + write16( 0xB70F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// mov r32+off to r32 +void MOV32RmOffsettoR( x86IntRegType to, x86IntRegType from, u32 offset) +{ + if( offset == 0 ) { + MOV32RtoR(to, from); + return; + } + + write8(0x8d); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8( offset ); + } + else { + ModRM( 2, to, from ); + write32( offset ); + } +} + +// mov r32+r32 to r32 +void MOV32Rm2toR( x86IntRegType to, x86IntRegType from1, x86IntRegType from2) +{ + write8(0x8d); + ModRM( 0, to, 4 ); + ModRM( 0, from1, from2 ); +} + +/* cmovbe r32 to r32 */ +void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x46, to, from ); +} + +/* cmovbe m32 to r32*/ +void CMOVBE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x46, to, from ); +} + +/* cmovb r32 to r32 */ +void CMOVB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x42, to, from ); +} + +/* cmovb m32 to r32*/ +void CMOVB32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x42, to, from ); +} + +/* cmovae r32 to r32 */ +void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x43, to, from ); +} + +/* cmovae m32 to r32*/ +void CMOVAE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x43, to, from ); +} + +/* cmova r32 to r32 */ +void CMOVA32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x47, to, from ); +} + +/* cmova m32 to r32*/ +void CMOVA32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x47, to, from ); +} + +/* cmovo r32 to r32 */ +void CMOVO32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x40, to, from ); +} + +/* cmovo m32 to r32 */ +void CMOVO32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x40, to, from ); +} + +/* cmovp r32 to r32 */ +void CMOVP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4A, to, from ); +} + +/* cmovp m32 to r32 */ +void CMOVP32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4A, to, from ); +} + +/* cmovs r32 to r32 */ +void CMOVS32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x48, to, from ); +} + +/* cmovs m32 to r32 */ +void CMOVS32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x48, to, from ); +} + +/* cmovno r32 to r32 */ +void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x41, to, from ); +} + +/* cmovno m32 to r32 */ +void CMOVNO32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x41, to, from ); +} + +/* cmovnp r32 to r32 */ +void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4B, to, from ); +} + +/* cmovnp m32 to r32 */ +void CMOVNP32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4B, to, from ); +} + +/* cmovns r32 to r32 */ +void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x49, to, from ); +} + +/* cmovns m32 to r32 */ +void CMOVNS32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x49, to, from ); +} + +/* cmovne r32 to r32 */ +void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x45, to, from ); +} + +/* cmovne m32 to r32*/ +void CMOVNE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x45, to, from ); +} + +/* cmove r32 to r32*/ +void CMOVE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x44, to, from ); +} + +/* cmove m32 to r32*/ +void CMOVE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x44, to, from ); +} + +/* cmovg r32 to r32*/ +void CMOVG32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4F, to, from ); +} + +/* cmovg m32 to r32*/ +void CMOVG32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4F, to, from ); +} + +/* cmovge r32 to r32*/ +void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4D, to, from ); +} + +/* cmovge m32 to r32*/ +void CMOVGE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4D, to, from ); +} + +/* cmovl r32 to r32*/ +void CMOVL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4C, to, from ); +} + +/* cmovl m32 to r32*/ +void CMOVL32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4C, to, from ); +} + +/* cmovle r32 to r32*/ +void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4E, to, from ); +} + +/* cmovle m32 to r32*/ +void CMOVLE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4E, to, from ); +} + +//////////////////////////////////// +// arithmetic instructions / +//////////////////////////////////// + +/* add imm32 to r64 */ +void ADD64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX) { + write8( 0x05 ); + } else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add m64 to r64 */ +void ADD64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* add r64 to r64 */ +void ADD64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add imm32 to r32 */ +void ADD32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, to >> 3, 0, 0); + } + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add imm32 to m32 */ +void ADD32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* add r32 to r32 */ +void ADD32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add r32 to m32 */ +void ADD32RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m32 to r32 */ +void ADD32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add r16 to r16 +void ADD16RtoR( x86IntRegType to , x86IntRegType from ) +{ + write16( 0x0366 ); + ModRM( 3, to, from ); +} + +/* add imm16 to r16 */ +void ADD16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +/* add imm16 to m16 */ +void ADD16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* add r16 to m16 */ +void ADD16RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m16 to r16 */ +void ADD16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add m8 to r8 +void ADD8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x02 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* adc imm32 to r32 */ +void ADC32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x15 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 2, to ); + } + write32( from ); +} + +/* adc imm32 to m32 */ +void ADC32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* adc r32 to r32 */ +void ADC32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x11 ); + ModRM( 3, from, to ); +} + +/* adc m32 to r32 */ +void ADC32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x13 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// adc r32 to m32 +void ADC32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x11 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r32 */ +void INC32R( x86IntRegType to ) +{ + write8( 0x40 + to ); +} + +/* inc m32 */ +void INC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r16 */ +void INC16R( x86IntRegType to ) +{ + write8( 0x66 ); + write8( 0x40 + to ); +} + +/* inc m16 */ +void INC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* sub imm32 to r64 */ +void SUB64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) + { + write8( 0x2D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub r64 to r64 */ +void SUB64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m64 to r64 */ +void SUB64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sub imm32 to r32 */ +void SUB32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x2D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub imm32 to m32 */ +void SUB32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sub r32 to r32 */ +void SUB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m32 to r32 */ +void SUB32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// sub r32 to m32 +void SUB32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x29 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// sub r16 to r16 +void SUB16RtoR( x86IntRegType to, u16 from ) +{ + write16( 0x2b66 ); + ModRM( 3, to, from ); +} + +/* sub imm16 to r16 */ +void SUB16ItoR( x86IntRegType to, u16 from ) { + write8( 0x66 ); + if ( to == EAX ) { + write8( 0x2D ); + } else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write16( from ); +} + +/* sub imm16 to m16 */ +void SUB16ItoM( u32 to, u16 from ) { + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* sub m16 to r16 */ +void SUB16MtoR( x86IntRegType to, u32 from ) { + write8( 0x66 ); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r64 to r64 */ +void SBB64RtoR( x86IntRegType to, x86IntRegType from ) { + Rex(1, to >> 3, 0, from >> 3); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb imm32 to r32 */ +void SBB32ItoR( x86IntRegType to, u32 from ) { + if ( to == EAX ) { + write8( 0x1D ); + } else { + write8( 0x81 ); + ModRM( 3, 3, to ); + } + write32( from ); +} + +/* sbb imm32 to m32 */ +void SBB32ItoM( u32 to, u32 from ) { + write8( 0x81 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sbb r32 to r32 */ +void SBB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb m32 to r32 */ +void SBB32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x1B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r32 to m32 */ +void SBB32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x19 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* dec r32 */ +void DEC32R( x86IntRegType to ) +{ + write8( 0x48 + to ); +} + +/* dec m32 */ +void DEC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* dec r16 */ +void DEC16R( x86IntRegType to ) +{ + write8( 0x66 ); + write8( 0x48 + to ); +} + +/* dec m16 */ +void DEC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mul eax by r32 to edx:eax */ +void MUL32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 4, from ); +} + +/* imul eax by r32 to edx:eax */ +void IMUL32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 5, from ); +} + +/* mul eax by m32 to edx:eax */ +void MUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul eax by m32 to edx:eax */ +void IMUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul r32 by r32 to r32 */ +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xAF0F ); + ModRM( 3, to, from ); +} + +/* div eax by r32 to edx:eax */ +void DIV32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 6, from ); +} + +/* idiv eax by r32 to edx:eax */ +void IDIV32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 7, from ); +} + +/* div eax by m32 to edx:eax */ +void DIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* idiv eax by m32 to edx:eax */ +void IDIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////// +// shifting instructions / +//////////////////////////////////// + +/* shl imm8 to r64 */ +void SHL64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 4, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl cl to r64 */ +void SHL64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +/* shr imm8 to r64 */ +void SHR64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 5, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); +} + +/* shr cl to r64 */ +void SHR64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +/* shl imm8 to r32 */ +void SHL32ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl imm8 to m32 */ +void SHL32ItoM( u32 to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + write8( from ); + } +} + +/* shl cl to r32 */ +void SHL32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +// shl imm8 to r16 +void SHL16ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write16( 0xD166 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write16( 0xC166 ); + ModRM( 3, 4, to ); + write8( from ); +} + +// shl imm8 to r8 +void SHL8ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC0 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shr imm8 to r32 */ +void SHR32ItoR( x86IntRegType to, u8 from ) { + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* shr imm8 to m32 */ +void SHR32ItoM( u32 to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + write8( from ); + } +} + +/* shr cl to r32 */ +void SHR32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +// shr imm8 to r8 +void SHR8ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC0 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* sar imm8 to r64 */ +void SAR64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar cl to r64 */ +void SAR64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +/* sar imm8 to r32 */ +void SAR32ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar imm8 to m32 */ +void SAR32ItoM( u32 to, u8 from ) +{ + write8( 0xC1 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* sar cl to r32 */ +void SAR32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +// sar imm8 to r16 +void SAR16ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write16( 0xD166 ); + ModRM( 3, 7, to ); + return; + } + write16( 0xC166 ); + ModRM( 3, 7, to ); + write8( from ); +} + +void ROR32ItoR( x86IntRegType to,u8 from ) +{ + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xc8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xc8 | to ); + write8( from ); + } +} + +void RCR32ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xd8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xd8 | to ); + write8( from ); + } +} + +// shld imm8 to r32 +void SHLD32ItoR( u32 to, u32 from, u8 shift ) +{ + write8( 0x0F ); + write8( 0xA4 ); + ModRM( 3, from, to ); + write8( shift ); +} + +// shrd imm8 to r32 +void SHRD32ItoR( u32 to, u32 from, u8 shift ) +{ + write8( 0x0F ); + write8( 0xAC ); + ModRM( 3, from, to ); + write8( shift ); +} + +//////////////////////////////////// +// logical instructions / +//////////////////////////////////// + +/* or imm32 to r32 */ +void OR64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x0D ); + } else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or m64 to r64 */ +void OR64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* or r64 to r64 */ +void OR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x09 ); + ModRM( 3, from, to ); +} + + +/* or imm32 to r32 */ +void OR32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or imm32 to m32 */ +void OR32ItoM(u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* or r32 to r32 */ +void OR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x09 ); + ModRM( 3, from, to ); +} + +/* or r32 to m32 */ +void OR32RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x09 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* or m32 to r32 */ +void OR32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to r16 +void OR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0966 ); + ModRM( 3, from, to ); +} + +// or imm16 to r16 +void OR16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) { + write16( 0x0D66 ); + } + else { + write16( 0x8166 ); + ModRM( 3, 1, to ); + } + write16( from ); +} + +// or imm16 to m316 +void OR16ItoM( u32 to, u16 from ) +{ + write16( 0x8166 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write16( from ); +} + +/* or m16 to r16 */ +void OR16MtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0B66 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to m16 +void OR16RtoM( u32 to, x86IntRegType from ) +{ + write16( 0x0966 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or r8 to r8 +void OR8RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x08 ); + ModRM( 3, from, to ); +} + +// or r8 to m8 +void OR8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x08 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or imm8 to m8 +void OR8ItoM( u32 to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +// or m8 to r8 +void OR8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x0A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r64 */ +void XOR64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x35 ); + } else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor r64 to r64 */ +void XOR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor m64 to r64 */ +void XOR64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r32 */ +void XOR32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor imm32 to m32 */ +void XOR32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* xor r32 to r32 */ +void XOR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r16 to r16 */ +void XOR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r32 to m32 */ +void XOR32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x31 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* xor m32 to r32 */ +void XOR32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// xor imm16 to r16 +void XOR16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) { + write16( 0x3566 ); + } + else { + write16( 0x8166 ); + ModRM( 3, 6, to ); + } + write16( from ); +} + +// xor r16 to m16 +void XOR16RtoM( u32 to, x86IntRegType from ) +{ + write16( 0x3166 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and imm32 to r64 */ +void AND64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and m64 to r64 */ +void AND64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* and r64 to m64 */ +void AND64RtoM( u32 to, x86IntRegType from ) +{ + Rex(1, 0, 0, 0); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and r64 to r64 */ +void AND64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and imm32 to r32 */ +void AND32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and sign ext imm8 to r32 */ +void AND32I8toR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0x83 ); + ModRM( 3, 0x4, to ); + write8( from ); +} + +/* and imm32 to m32 */ +void AND32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* and sign ext imm8 to m32 */ +void AND32I8toM( u32 to, u8 from ) +{ + write8( 0x83 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* and r32 to r32 */ +void AND32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and r32 to m32 */ +void AND32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m32 to r32 */ +void AND32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// and r16 to r16 +void AND16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x2366 ); + ModRM( 3, to, from ); +} + +/* and imm16 to r16 */ +void AND16ItoR( x86IntRegType to, u16 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write16( 0x2566 ); + } else { + write16( 0x8166 ); + ModRM( 3, 0x4, to ); + } + write16( from ); +} + +/* and imm16 to m16 */ +void AND16ItoM( u32 to, u16 from ) +{ + write8( 0x8166 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write16( from ); +} + +/* and r16 to m16 */ +void AND16RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m16 to r16 */ +void AND16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* and imm8 to r8 */ +void AND8ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write8( 0x24 ); + } else { + write8( 0x80 ); + ModRM( 3, 0x4, to ); + } + write8( from ); +} + +/* and imm8 to m8 */ +void AND8ItoM( u32 to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +// and r8 to r8 +void AND8RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x22 ); + ModRM( 3, to, from ); +} + +/* and r8 to m8 */ +void AND8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x20 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m8 to r8 */ +void AND8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x22 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* not r64 */ +void NOT64R( x86IntRegType from ) +{ + Rex(1, 0, 0, from >> 3); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +/* not r32 */ +void NOT32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +// not m32 +void NOT32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r64 */ +void NEG64R( x86IntRegType from ) +{ + Rex(1, from >> 3, 0, 0); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +/* neg r32 */ +void NEG32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +void NEG32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r16 */ +void NEG16R( x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +u8* JMP( u32 to ) { + u32 jump = ( x86Ptr - (s8*)to ) - 1; + + if ( jump > 0x7f ) { + return (u8*)JMP32( to ); + } else { + return (u8*)JMP8( to ); + } +} + +/* jmp rel8 */ +u8* JMP8( u8 to ) +{ + write8( 0xEB ); + write8( to ); + return x86Ptr - 1; +} + +/* jmp rel32 */ +u32* JMP32( u32 to ) +{ + write8( 0xE9 ); + write32( to ); + return (u32*)(x86Ptr - 4 ); +} + +/* jmp r32 */ +void JMP32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +// jmp m32 +void JMP32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4)); +} + +/* jmp r64 */ +void JMP64R( x86IntRegType to ) { + Rex(1, 0, 0, to >> 3); + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +/* jp rel8 */ +u8* JP8( u8 to ) { + return J8Rel( 0x7A, to ); +} + +/* jnp rel8 */ +u8* JNP8( u8 to ) { + return J8Rel( 0x7B, to ); +} + +/* je rel8 */ +u8* JE8( u8 to ) { + return J8Rel( 0x74, to ); +} + +/* jz rel8 */ +u8* JZ8( u8 to ) +{ + return J8Rel( 0x74, to ); +} + +/* js rel8 */ +u8* JS8( u8 to ) +{ + return J8Rel( 0x78, to ); +} + +/* jns rel8 */ +u8* JNS8( u8 to ) +{ + return J8Rel( 0x79, to ); +} + +/* jg rel8 */ +u8* JG8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jge rel8 */ +u8* JGE8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jl rel8 */ +u8* JL8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* ja rel8 */ +u8* JA8( u8 to ) +{ + return J8Rel( 0x77, to ); +} + +u8* JAE8( u8 to ) +{ + return J8Rel( 0x73, to ); +} + +/* jb rel8 */ +u8* JB8( u8 to ) +{ + return J8Rel( 0x72, to ); +} + +/* jbe rel8 */ +u8* JBE8( u8 to ) +{ + return J8Rel( 0x76, to ); +} + +/* jle rel8 */ +u8* JLE8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jne rel8 */ +u8* JNE8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jnz rel8 */ +u8* JNZ8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jng rel8 */ +u8* JNG8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jnge rel8 */ +u8* JNGE8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* jnl rel8 */ +u8* JNL8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jnle rel8 */ +u8* JNLE8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jo rel8 */ +u8* JO8( u8 to ) +{ + return J8Rel( 0x70, to ); +} + +/* jno rel8 */ +u8* JNO8( u8 to ) +{ + return J8Rel( 0x71, to ); +} + +// jb rel8 +u16* JB16( u16 to ) +{ + return J16Rel( 0x82, to ); +} + +// jb rel32 +u32* JB32( u32 to ) +{ + return J32Rel( 0x82, to ); +} + +/* je rel32 */ +u32* JE32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jz rel32 */ +u32* JZ32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jg rel32 */ +u32* JG32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jge rel32 */ +u32* JGE32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jl rel32 */ +u32* JL32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jle rel32 */ +u32* JLE32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jae rel32 */ +u32* JAE32( u32 to ) +{ + return J32Rel( 0x83, to ); +} + +/* jne rel32 */ +u32* JNE32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jnz rel32 */ +u32* JNZ32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jng rel32 */ +u32* JNG32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jnge rel32 */ +u32* JNGE32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jnl rel32 */ +u32* JNL32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jnle rel32 */ +u32* JNLE32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jo rel32 */ +u32* JO32( u32 to ) +{ + return J32Rel( 0x80, to ); +} + +/* jno rel32 */ +u32* JNO32( u32 to ) +{ + return J32Rel( 0x81, to ); +} + +// js rel32 +u32* JS32( u32 to ) +{ + return J32Rel( 0x88, to ); +} + + +/* call func */ +void CALLFunc( u32 func ) +{ + CALL32( func - ( (u32)x86Ptr + 5 ) ); +} + +/* call rel32 */ +void CALL32( u32 to ) +{ + write8( 0xE8 ); + write32( to ); +} + +/* call r32 */ +void CALL32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call r64 */ +void CALL64R( x86IntRegType to ) +{ + Rex(1, 0, 0, to >> 3); + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call m32 */ +void CALL32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +//////////////////////////////////// +// misc instructions / +//////////////////////////////////// + +/* cmp imm32 to r64 */ +void CMP64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp m64 to r64 */ +void CMP64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* cmp imm32 to r32 */ +void CMP32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp imm32 to m32 */ +void CMP32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* cmp r32 to r32 */ +void CMP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m32 to r32 */ +void CMP32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to [r32] +void CMP32I8toRm( x86IntRegType to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, to ); + write8(from); +} + +// cmp imm32 to [r32+off] +void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off) +{ + assert( to != ESP ); + write8( 0x83 ); + ModRM( 1, 7, to ); + write8(off); + write8(from); +} + +// cmp imm8 to [r32] +void CMP32I8toM( u32 to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* cmp imm16 to r16 */ +void CMP16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write16( from ); +} + +/* cmp imm16 to m16 */ +void CMP16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* cmp r16 to r16 */ +void CMP16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m16 to r16 */ +void CMP16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to r8 +void CMP8ItoR( x86IntRegType to, u8 from ) +{ + if ( to == EAX ) + { + write8( 0x3C ); + } + else + { + write8( 0x80 ); + ModRM( 3, 7, to ); + } + write8( from ); +} + +/* test imm32 to r32 */ +void TEST32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +void TEST32ItoM( u32 to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* test r32 to r32 */ +void TEST32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm32 to [r32] +void TEST32ItoRm( x86IntRegType to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, to ); + write32(from); +} + +// test imm16 to r16 +void TEST16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) + { + write16( 0xA966 ); + } + else + { + write16( 0xF766 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +// test r16 to r16 +void TEST16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x8566 ); + ModRM( 3, from, to ); +} + +// test imm8 to r8 +void TEST8ItoR( x86IntRegType to, u8 from ) +{ + if ( to == EAX ) + { + write8( 0xA8 ); + } + else + { + write8( 0xF6 ); + ModRM( 3, 0, to ); + } + write8( from ); +} + +// test imm8 to r8 +void TEST8ItoM( u32 to, u8 from ) +{ + write8( 0xF6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* sets r8 */ +void SETS8R( x86IntRegType to ) +{ + SET8R( 0x98, to ); +} + +/* setl r8 */ +void SETL8R( x86IntRegType to ) +{ + SET8R( 0x9C, to ); +} + +// setge r8 +void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); } +// setg r8 +void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); } +// seta r8 +void SETA8R( x86IntRegType to ) { SET8R(0x97, to); } +// setae r8 +void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); } +/* setb r8 */ +void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); } +/* setb r8 */ +void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); } +// setz r8 +void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); } +// sete r8 +void SETE8R( x86IntRegType to ) { SET8R(0x94, to); } + +/* push r32 */ +void PUSH32R( x86IntRegType from ) +{ + write8( 0x50 | from ); +} + +/* push m32 */ +void PUSH32M( u32 from ) +{ + write8( 0xFF ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* push imm32 */ +void PUSH32I( u32 from ) +{ + write8( 0x68 ); + write32( from ); +} + +/* pop r32 */ +void POP32R( x86IntRegType from ) +{ + write8( 0x58 | from ); +} + +/* pushad */ +void PUSHA32( void ) +{ + write8( 0x60 ); +} + +/* popad */ +void POPA32( void ) +{ + write8( 0x61 ); +} + +/* pushfd */ +void PUSHFD( void ) +{ + write8( 0x9C ); +} + +/* popfd */ +void POPFD( void ) +{ + write8( 0x9D ); +} + +void RET( void ) { write8( 0xC3 ); } +void RET2( void ) { write16( 0xc3f3 ); } + +void CBW( void ) { write16( 0x9866 ); } +void CWD( void ) { write8( 0x98 ); } +void CDQ( void ) { write8( 0x99 ); } +void CWDE() { write8(0x98); } + +void LAHF() { write8(0x9f); } +void SAHF() { write8(0x9e); } + +void BT32ItoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBA0F ); + write8( 0xE0 | to ); + write8( from ); +} + +void BSRRtoR(x86IntRegType to, x86IntRegType from) +{ + write16( 0xBD0F ); + ModRM( 3, from, to ); +} + +void BSWAP32R( x86IntRegType to ) +{ + write8( 0x0F ); + write8( 0xC8 + to ); +} + +// to = from + offset +void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset) +{ + write8(0x66); + LEA32RtoR(to, from, offset); +} + +void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8(0x8d); + + if( from == ESP ) { + if( offset == 0 ) { + ModRM(1, to, from); + write8(0x24); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(0x24); + write8(offset); + } + else { + ModRM(2, to, from); + write8(0x24); + write32(offset); + } + } + else { + if( offset == 0 && from != EBP && from!=ESP ) { + ModRM(0, to, from); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(offset); + } + else { + ModRM(2, to, from); + write32(offset); + } + } +} + +// to = from0 + from1 +void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x66); + LEA32RRtoR(to, from0, from1); +} + +void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x8d); + if( from0 == EBP || from1 == EBP ) { + + if( from0 == EBP ) SWAP(from0, from1); + ModRM(1, to, 4); + ModRM(0, from0, from1); + write8(0); + } + else { + ModRM(0, to, 4); + ModRM(0, from0, from1); + } +} + +// to = from << scale (max is 3) +void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + write8(0x66); + LEA32RStoR(to, from, scale); +} + +void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + if( to == from ) { + SHL32ItoR(to, scale); + return; + } + + if( from != ESP ) { + write8(0x8d); + ModRM(0, to, 4); + ModRM(scale, from, 5); + write32(0); + } + else { + MOV32RtoR(to, from); + LEA32RStoR(to, to, scale); + } +} diff --git a/x86/ix86/ix86.h b/x86/ix86/ix86.h new file mode 100644 index 0000000000..4fbdd20eda --- /dev/null +++ b/x86/ix86/ix86.h @@ -0,0 +1,1637 @@ +/* + * ix86 definitions v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * shadow < shadow@pcsx2.net > + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "PS2Etypes.h" // Basic types header + +#ifdef __x86_64__ +#define XMMREGS 16 +#define X86REGS 16 +#else +#define XMMREGS 8 +#define X86REGS 8 +#endif + +#define MMXREGS 8 + +#define SIB 4 +#define DISP32 5 + +// general types +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 +#define RAX 0 +#define RBX 3 +#define RCX 1 +#define RDX 2 +#define RSI 6 +#define RDI 7 +#define RBP 5 +#define RSP 4 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +typedef int x86IntRegType; + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +typedef int x86MMXRegType; + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 +#define XMM8 8 +#define XMM9 9 +#define XMM10 10 +#define XMM11 11 +#define XMM12 12 +#define XMM13 13 +#define XMM14 14 +#define XMM15 15 + +typedef int x86SSERegType; + +typedef enum +{ + XMMT_INT = 0, // integer (sse2 only) + XMMT_FPS = 1, // floating point + //XMMT_FPD = 3, // double +} XMMSSEType; + +extern XMMSSEType g_xmmtypes[XMMREGS]; + +void cpudetectInit( void );//this is all that needs to be called and will fill up the below structs + +//cpu capabilities structure +typedef struct { + u32 hasFloatingPointUnit; + u32 hasVirtual8086ModeEnhancements; + u32 hasDebuggingExtensions; + u32 hasPageSizeExtensions; + u32 hasTimeStampCounter; + u32 hasModelSpecificRegisters; + u32 hasPhysicalAddressExtension; + u32 hasCOMPXCHG8BInstruction; + u32 hasAdvancedProgrammableInterruptController; + u32 hasSEPFastSystemCall; + u32 hasMemoryTypeRangeRegisters; + u32 hasPTEGlobalFlag; + u32 hasMachineCheckArchitecture; + u32 hasConditionalMoveAndCompareInstructions; + u32 hasFGPageAttributeTable; + u32 has36bitPageSizeExtension; + u32 hasProcessorSerialNumber; + u32 hasCFLUSHInstruction; + u32 hasDebugStore; + u32 hasACPIThermalMonitorAndClockControl; + u32 hasMultimediaExtensions; + u32 hasFastStreamingSIMDExtensionsSaveRestore; + u32 hasStreamingSIMDExtensions; + u32 hasStreamingSIMD2Extensions; + u32 hasSelfSnoop; + u32 hasHyperThreading; + u32 hasThermalMonitor; + u32 hasIntel64BitArchitecture; + u32 hasStreamingSIMD3Extensions; + //that is only for AMDs + u32 hasMultimediaExtensionsExt; + u32 hasAMD64BitArchitecture; + u32 has3DNOWInstructionExtensionsExt; + u32 has3DNOWInstructionExtensions; +} CAPABILITIES; + +extern CAPABILITIES cpucaps; + +typedef struct { + + u32 x86Family; // Processor Family + u32 x86Model; // Processor Model + u32 x86PType; // Processor Type + u32 x86StepID; // Stepping ID + u32 x86Flags; // Feature Flags + u32 x86EFlags; // Extended Feature Flags + //all the above returns hex values + s8 x86ID[16]; // Vendor ID //the vendor creator (in %s) + s8 x86Type[20]; //cpu type in char format //the cpu type (in %s) + s8 x86Fam[50]; // family in char format //the original cpu name string (in %s) + u32 cpuspeed; // speed of cpu //this will give cpu speed (in %d) +} CPUINFO; + +extern CPUINFO cpuinfo; + +extern s8 *x86Ptr; +extern u8 *j8Ptr[32]; +extern u32 *j32Ptr[32]; + + +#ifdef __x86_64__ +#define MEMADDR(addr, oplen) ((addr) - ((u64)x86Ptr + ((u64)oplen))) +#else +#define MEMADDR(addr, oplen) (addr) +#endif + + + +void write8( int val ); +void write16( int val ); +void write32( u32 val ); +void write64( u64 val ); + + +void x86SetPtr( char *ptr ); +void x86Shutdown( void ); + +void x86SetJ8( u8 *j8 ); +void x86SetJ8A( u8 *j8 ); +void x86SetJ16( u16 *j16 ); +void x86SetJ16A( u16 *j16 ); +void x86SetJ32( u32 *j32 ); +void x86SetJ32A( u32 *j32 ); + +void x86Align( int bytes ); +u64 GetCPUTick( void ); + +// General Helper functions + +void Rex( int w, int r, int x, int b ); +void ModRM( int mod, int rm, int reg ); +void SibSB( int ss, int rm, int index ); +void SET8R( int cc, int to ); +u8* J8Rel( int cc, int to ); +u32* J32Rel( int cc, u32 to ); +void CMOV32RtoR( int cc, int to, int from ); +void CMOV32MtoR( int cc, int to, u32 from ); + +//****************** +// IX86 intructions +//****************** + +// +// * scale values: +// * 0 - *1 +// * 1 - *2 +// * 2 - *4 +// * 3 - *8 +// + +void STC( void ); +void CLC( void ); + +//////////////////////////////////// +// mov instructions // +//////////////////////////////////// + +// mov r64 to r64 +void MOV64RtoR( x86IntRegType to, x86IntRegType from ); +// mov r64 to m64 +void MOV64RtoM( u64 to, x86IntRegType from ); +// mov m64 to r64 +void MOV64MtoR( x86IntRegType to, u64 from ); +// mov imm32 to m64 +void MOV64ItoM( u32 to, u32 from ); + +// mov r32 to r32 +void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +void MOV32RtoM( u32 to, x86IntRegType from ); +// mov m32 to r32 +void MOV32MtoR( x86IntRegType to, u32 from ); +// mov [r32] to r32 +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ); +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ); +// mov [r32][r32< subtract ST(0) from ST(1), store in ST(1) and POP stack +void FSUBP( void ); +// fmul ST(src) to fpu reg stack ST(0) +void FMUL32Rto0( x86IntRegType src ); +// fmul ST(0) to fpu reg stack ST(src) +void FMUL320toR( x86IntRegType src ); +// fdiv ST(src) to fpu reg stack ST(0) +void FDIV32Rto0( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src) +void FDIV320toR( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src), pop stack, store in ST(src) +void FDIV320toRP( x86IntRegType src ); + +// fadd m32 to fpu reg stack +void FADD32( u32 from ); +// fsub m32 to fpu reg stack +void FSUB32( u32 from ); +// fmul m32 to fpu reg stack +void FMUL32( u32 from ); +// fdiv m32 to fpu reg stack +void FDIV32( u32 from ); +// fcomi st, st( i) +void FCOMI( x86IntRegType src ); +// fcomip st, st( i) +void FCOMIP( x86IntRegType src ); +// fucomi st, st( i) +void FUCOMI( x86IntRegType src ); +// fucomip st, st( i) +void FUCOMIP( x86IntRegType src ); +// fcom m32 to fpu reg stack +void FCOM32( u32 from ); +// fabs fpu reg stack +void FABS( void ); +// fsqrt fpu reg stack +void FSQRT( void ); +// ftan fpu reg stack +void FPATAN( void ); +// fsin fpu reg stack +void FSIN( void ); +// fchs fpu reg stack +void FCHS( void ); + +// fcmovb fpu reg to fpu reg stack +void FCMOVB32( x86IntRegType from ); +// fcmove fpu reg to fpu reg stack +void FCMOVE32( x86IntRegType from ); +// fcmovbe fpu reg to fpu reg stack +void FCMOVBE32( x86IntRegType from ); +// fcmovu fpu reg to fpu reg stack +void FCMOVU32( x86IntRegType from ); +// fcmovnb fpu reg to fpu reg stack +void FCMOVNB32( x86IntRegType from ); +// fcmovne fpu reg to fpu reg stack +void FCMOVNE32( x86IntRegType from ); +// fcmovnbe fpu reg to fpu reg stack +void FCMOVNBE32( x86IntRegType from ); +// fcmovnu fpu reg to fpu reg stack +void FCMOVNU32( x86IntRegType from ); +void FCOMP32( u32 from ); +void FNSTSWtoAX( void ); + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +void MOVQMtoR( x86MMXRegType to, u32 from ); +// movq r64 to m64 +void MOVQRtoM( u32 to, x86MMXRegType from ); + +// pand r64 to r64 +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pand m64 to r64 ; +void PANDMtoR( x86MMXRegType to, u32 from ); +// pandn r64 to r64 +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +void PANDNMtoR( x86MMXRegType to, u32 from ); +// por r64 to r64 +void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +void PORMtoR( x86MMXRegType to, u32 from ); +// pxor r64 to r64 +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +void PXORMtoR( x86MMXRegType to, u32 from ); + +// psllq r64 to r64 +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +void PSLLQMtoR( x86MMXRegType to, u32 from ); +// psllq imm8 to r64 +void PSLLQItoR( x86MMXRegType to, u8 from ); +// psrlq r64 to r64 +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psrlq m64 to r64 +void PSRLQMtoR( x86MMXRegType to, u32 from ); +// psrlq imm8 to r64 +void PSRLQItoR( x86MMXRegType to, u8 from ); + +// paddusb r64 to r64 +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusb m64 to r64 +void PADDUSBMtoR( x86MMXRegType to, u32 from ); +// paddusw r64 to r64 +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +void PADDUSWMtoR( x86MMXRegType to, u32 from ); + +// paddb r64 to r64 +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +void PADDBMtoR( x86MMXRegType to, u32 from ); +// paddw r64 to r64 +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +void PADDWMtoR( x86MMXRegType to, u32 from ); +// paddd r64 to r64 +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +void PADDDMtoR( x86MMXRegType to, u32 from ); +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, u32 from ); +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDMtoR( x86MMXRegType to, u32 from ); + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, u32 from ); +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ); + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, u32 from ); +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDMtoR( x86MMXRegType to, u32 from ); +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDMtoR( x86MMXRegType to, u32 from ); +void PSRLWItoR( x86MMXRegType to, u8 from ); +void PSRLDItoR( x86MMXRegType to, u8 from ); +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSLLWItoR( x86MMXRegType to, u8 from ); +void PSLLDItoR( x86MMXRegType to, u8 from ); +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSRAWItoR( x86MMXRegType to, u8 from ); +void PSRADItoR( x86MMXRegType to, u8 from ); +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQMtoR( x86MMXRegType to, u32 from ); +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKHDQMtoR( x86MMXRegType to, u32 from ); +void MOVQ64ItoR( x86MMXRegType reg, u64 i ); //Prototype.Todo add all consts to end of block.not after jr $+8 +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ); +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void MOVDMtoMMX( x86MMXRegType to, u32 from ); +void MOVDMMXtoM( u32 to, x86MMXRegType from ); +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ); +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8); +void PSHUFWMtoR(x86MMXRegType to, u32 from, u8 imm8); +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from); + +// emms +void EMMS( void ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word 64bits +//********************************************************************************** +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from); +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from); + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from); + +//********************* +// SSE instructions * +//********************* +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVAPS_XMM_to_M128( u32 to, x86SSERegType from ); +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVUPS_XMM_to_M128( u32 to, x86SSERegType from ); + +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVLPSRmtoR( x86MMXRegType to, x86IntRegType from ); +void SSE_MOVLPSRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void SSE_MOVLPSRtoRm( x86MMXRegType to, x86IntRegType from ); +void SSE_MOVLPSRtoRmOffset( x86MMXRegType to, x86IntRegType from, u32 offset ); + +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ); +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ); + +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, u32 offset ); + +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); + +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, u32 from ); + +void SSE_ORPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_XORPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ); +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, u32 from ); +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ); +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, u32 from); +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, u32 from); +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from); + +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset, u8 imm8 ); +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +// VectorPath +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); + +void SSE_STMXCSR( u32 from ); +void SSE_LDMXCSR( u32 from ); + + +//********************* +// SSE 2 Instructions* +//********************* +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from); +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from); +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PAND_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, u32 from ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, u32 from); + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, u32 from); + +// mult by half words +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, u32 from); + + +//**********************************************************************************/ +//PMOVMSKB: Create 16bit mask from signs of 8bit integers +//********************************************************************************** +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ); +void SSE_PINSRW_R32_to_XMM(x86SSERegType from, x86IntRegType to, u8 imm8 ); + + +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, u32 from ); +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, u32 from ); +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_POR_M128_to_XMM( x86SSERegType to, u32 from ); + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, u32 from); +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, u32 from); +//********************* +// SSE-X - uses both SSE,SSE2 code and tries to keep consistensies between the data +// Uses g_xmmtypes to infer the correct type. +//********************* +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ); +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from ); +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSEX_POR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PAND_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +//********************* +// 3DNOW instructions * +//********************* +void FEMMS( void ); +void PFCMPEQMtoR( x86IntRegType to, u32 from ); +void PFCMPGTMtoR( x86IntRegType to, u32 from ); +void PFCMPGEMtoR( x86IntRegType to, u32 from ); +void PFADDMtoR( x86IntRegType to, u32 from ); +void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +void PFSUBMtoR( x86IntRegType to, u32 from ); +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +void PFMULMtoR( x86IntRegType to, u32 from ); +void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPMtoR( x86IntRegType to, u32 from ); +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PF2IDMtoR( x86IntRegType to, u32 from ); +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ); +void PI2FDMtoR( x86IntRegType to, u32 from ); +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +void PFMAXMtoR( x86IntRegType to, u32 from ); +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +void PFMINMtoR( x86IntRegType to, u32 from ); +void PFMINRtoR( x86IntRegType to, x86IntRegType from ); + +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, u32 from); +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +/* SSE2 emulated functions for SSE CPU's by kekko*/ + +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); + +//////////////////////////////////////////////////// +#ifdef _DEBUG +#define WRITECHECK() CheckX86Ptr() +#else +#define WRITECHECK() +#endif + +#define write8(val ) { \ + *(u8*)x86Ptr = (u8)val; \ + x86Ptr++; \ +} \ + +#define write16(val ) \ +{ \ + *(u16*)x86Ptr = (u16)val; \ + x86Ptr += 2; \ +} \ + +#define write32( val ) \ +{ \ + *(u32*)x86Ptr = val; \ + x86Ptr += 4; \ +} \ + +#ifdef __cplusplus +} +#endif + +#endif // __IX86_H__ diff --git a/x86/ix86/ix86_3dnow.c b/x86/ix86/ix86_3dnow.c new file mode 100644 index 0000000000..df56fd075d --- /dev/null +++ b/x86/ix86/ix86_3dnow.c @@ -0,0 +1,184 @@ + +#include "ix86.h" + +/**********************/ +/* 3DNOW instructions */ +/**********************/ + +/* femms */ +void FEMMS( void ) +{ + write16( 0x0E0F ); +} + +void PFCMPEQMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB0 ); +} + +void PFCMPGTMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA0 ); +} + +void PFCMPGEMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x90 ); +} + +void PFADDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9E ); +} + +void PFADDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9E ); +} + +void PFSUBMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9A ); +} + +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9A ); +} + +void PFMULMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB4 ); +} + +void PFMULRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB4 ); +} + +void PFRCPMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x96 ); +} + +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x96 ); +} + +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA6 ); +} + +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB6 ); +} + +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x97 ); +} + +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA7 ); +} + +void PF2IDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x1D ); +} + +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x1D ); +} + +void PI2FDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x0D ); +} + +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x0D ); +} + +void PFMAXMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA4 ); +} + +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA4 ); +} + +void PFMINMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x94 ); +} + +void PFMINRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x94 ); +} diff --git a/x86/ix86/ix86_cpudetect.c b/x86/ix86/ix86_cpudetect.c new file mode 100644 index 0000000000..5d32ebf0a9 --- /dev/null +++ b/x86/ix86/ix86_cpudetect.c @@ -0,0 +1,482 @@ +/* Cpudetection lib + * Copyright (C) 2002-2003 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if defined (__WIN32__) + +#include + +#endif + +#include +#include + +#include "ix86.h" + +#if defined (__VCNET2005__) + + void __cpuid(int* CPUInfo, int InfoType); + unsigned __int64 __rdtsc(); + + #pragma intrinsic(__cpuid) + #pragma intrinsic(__rdtsc) + +#endif + +CAPABILITIES cpucaps; +CPUINFO cpuinfo; + +static s32 iCpuId( u32 cmd, u32 *regs ) +{ + int flag; + +#if defined (__VCNET2005__) + + __cpuid( regs, cmd ); + + return 0; + +#elif defined (__MSCW32__) && !defined(__x86_64__) + __asm + { + push ebx; + push edi; + + pushfd; + pop eax; + mov edx, eax; + xor eax, 1 << 21; + push eax; + popfd; + pushfd; + pop eax; + xor eax, edx; + mov flag, eax; + } + if ( ! flag ) + { + return -1; + } + + __asm + { + mov eax, cmd; + cpuid; + mov edi, [regs] + mov [edi], eax; + mov [edi+4], ebx; + mov [edi+8], ecx; + mov [edi+12], edx; + + pop edi; + pop ebx; + } + + return 0; + + +#else + + __asm__ __volatile__ ( +#ifdef __x86_64__ + "sub $0x18, %%rsp\n" +#endif + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%edx\n" + "xor $0x200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%eax\n" + "mov %%eax, %0\n" +#ifdef __x86_64__ + "add $0x18, %%rsp\n" +#endif + : "=r"(flag) : + ); + + if ( ! flag ) + { + return -1; + } + + __asm__ __volatile__ ( + "mov %4, %%eax\n" + "cpuid\n" + "mov %%eax, %0\n" + "mov %%ebx, %1\n" + "mov %%ecx, %2\n" + "mov %%edx, %3\n" + : "=m" (regs[0]), "=m" (regs[1]), + "=m" (regs[2]), "=m" (regs[3]) + : "m"(cmd) + : "eax", "ebx", "ecx", "edx" + ); + + return 0; +#endif +} + +u64 GetCPUTick( void ) +{ +#if defined (__VCNET2005__) + + return __rdtsc(); + +#elif defined(__MSCW32__) && !defined(__x86_64__) + + __asm rdtsc; + +#else + + u32 _a, _d; + __asm__ __volatile__ ("rdtsc" : "=a"(_a), "=d"(_d)); + return (u64)_a | ((u64)_d << 32); + +#endif +} + +#if defined __LINUX__ + +#include +#include + +u32 timeGetTime( void ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +#endif + +s64 CPUSpeedHz( unsigned int time ) +{ + s64 timeStart, + timeStop; + s64 startTick, + endTick; + s64 overhead; + + if( ! cpucaps.hasTimeStampCounter ) + { + return 0; //check if function is supported + } + + overhead = GetCPUTick() - GetCPUTick(); + + timeStart = timeGetTime( ); + while( timeGetTime( ) == timeStart ) + { + timeStart = timeGetTime( ); + } + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > 1 ) + { + startTick = GetCPUTick( ); + break; + } + } + + timeStart = timeStop; + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > time ) + { + endTick = GetCPUTick( ); + break; + } + } + + return (s64)( ( endTick - startTick ) + ( overhead ) ); +} + +//////////////////////////////////////////////////// +void cpudetectInit( void ) +{ + u32 regs[ 4 ]; + u32 cmds; + u32 AMDspeed; + s8 AMDspeedString[10]; + int cputype=0; // Cpu type + //AMD 64 STUFF + u32 x86_64_8BITBRANDID; + u32 x86_64_12BITBRANDID; + memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) ); + cpuinfo.x86Family = 0; + cpuinfo.x86Model = 0; + cpuinfo.x86PType = 0; + cpuinfo.x86StepID = 0; + cpuinfo.x86Flags = 0; + cpuinfo.x86EFlags = 0; + + if ( iCpuId( 0, regs ) == -1 ) return; + + cmds = regs[ 0 ]; + ((u32*)cpuinfo.x86ID)[ 0 ] = regs[ 1 ]; + ((u32*)cpuinfo.x86ID)[ 1 ] = regs[ 3 ]; + ((u32*)cpuinfo.x86ID)[ 2 ] = regs[ 2 ]; + if ( cmds >= 0x00000001 ) + { + if ( iCpuId( 0x00000001, regs ) != -1 ) + { + cpuinfo.x86StepID = regs[ 0 ] & 0xf; + cpuinfo.x86Model = (regs[ 0 ] >> 4) & 0xf; + cpuinfo.x86Family = (regs[ 0 ] >> 8) & 0xf; + cpuinfo.x86PType = (regs[ 0 ] >> 12) & 0x3; + x86_64_8BITBRANDID = regs[1] & 0xff; + cpuinfo.x86Flags = regs[ 3 ]; + } + } + if ( iCpuId( 0x80000000, regs ) != -1 ) + { + cmds = regs[ 0 ]; + if ( cmds >= 0x80000001 ) + { + if ( iCpuId( 0x80000001, regs ) != -1 ) + { + x86_64_12BITBRANDID = regs[1] & 0xfff; + cpuinfo.x86EFlags = regs[ 3 ]; + + } + } + } + switch(cpuinfo.x86PType) + { + case 0: + strcpy( cpuinfo.x86Type, "Standard OEM"); + break; + case 1: + strcpy( cpuinfo.x86Type, "Overdrive"); + break; + case 2: + strcpy( cpuinfo.x86Type, "Dual"); + break; + case 3: + strcpy( cpuinfo.x86Type, "Reserved"); + break; + default: + strcpy( cpuinfo.x86Type, "Unknown"); + break; + } + if ( cpuinfo.x86ID[ 0 ] == 'G' ){ cputype=0;}//trick lines but if you know a way better ;p + if ( cpuinfo.x86ID[ 0 ] == 'A' ){ cputype=1;} + + if ( cputype == 0 ) //intel cpu + { + if( ( cpuinfo.x86Family >= 7 ) && ( cpuinfo.x86Family < 15 ) ) + { + strcpy( cpuinfo.x86Fam, "Intel P6 family (Not PIV and Higher then PPro" ); + } + else + { + switch( cpuinfo.x86Family ) + { + // Start at 486 because if it's below 486 there is no cpuid instruction + case 4: + strcpy( cpuinfo.x86Fam, "Intel 486" ); + break; + case 5: + switch( cpuinfo.x86Model ) + { + case 4: + case 8: // 0.25 µm + strcpy( cpuinfo.x86Fam, "Intel Pentium (MMX)"); + break; + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium" ); + } + break; + case 6: + switch( cpuinfo.x86Model ) + { + case 0: // Pentium pro (P6 A-Step) + case 1: // Pentium pro + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro" ); + break; + + case 2: // 66 MHz FSB + case 5: // Xeon/Celeron (0.25 µm) + case 6: // Internal L2 cache + strcpy( cpuinfo.x86Fam, "Intel Pentium II" ); + break; + + case 7: // Xeon external L2 cache + case 8: // Xeon/Celeron with 256 KB on-die L2 cache + case 10: // Xeon/Celeron with 1 or 2 MB on-die L2 cache + case 11: // Xeon/Celeron with Tualatin core, on-die cache + strcpy( cpuinfo.x86Fam, "Intel Pentium III" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro (Unknown)" ); + } + break; + case 15: + switch( cpuinfo.x86Model ) + { + case 0: // Willamette (A-Step) + case 1: // Willamette + strcpy( cpuinfo.x86Fam, "Willamette Intel Pentium IV" ); + break; + case 2: // Northwood + strcpy( cpuinfo.x86Fam, "Northwood Intel Pentium IV" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium IV (Unknown)" ); + break; + } + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown Intel CPU" ); + } + } + } + else if ( cputype == 1 ) //AMD cpu + { + if( cpuinfo.x86Family >= 7 ) + { + if((x86_64_12BITBRANDID !=0) || (x86_64_8BITBRANDID !=0)) + { + if(x86_64_8BITBRANDID == 0 ) + { + switch((x86_64_12BITBRANDID >>6)& 0x3f) + { + case 4: + strcpy(cpuinfo.x86Fam,"AMD Athlon(tm) 64 Processor"); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(cpuinfo.x86Fam,AMDspeedString); + break; + case 12: + strcpy(cpuinfo.x86Fam,"AMD Opteron(tm) Processor"); + break; + default: + strcpy(cpuinfo.x86Fam,"Unknown AMD 64 proccesor"); + + } + } + else //8bit brand id is non zero + { + strcpy(cpuinfo.x86Fam,"Unsupported yet AMD64 cpu"); + } + } + else + { + strcpy( cpuinfo.x86Fam, "AMD K7+" ); + } + } + else + { + switch ( cpuinfo.x86Family ) + { + case 4: + switch( cpuinfo.x86Model ) + { + case 14: + case 15: // Write-back enhanced + strcpy( cpuinfo.x86Fam, "AMD 5x86" ); + break; + + case 3: // DX2 + case 7: // Write-back enhanced DX2 + case 8: // DX4 + case 9: // Write-back enhanced DX4 + strcpy( cpuinfo.x86Fam, "AMD 486" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown" ); + + } + break; + + case 5: + switch( cpuinfo.x86Model) + { + case 0: // SSA 5 (75, 90 and 100 Mhz) + case 1: // 5k86 (PR 120 and 133 MHz) + case 2: // 5k86 (PR 166 MHz) + case 3: // K5 5k86 (PR 200 MHz) + strcpy( cpuinfo.x86Fam, "AMD K5" ); + break; + + case 6: + case 7: // (0.25 µm) + case 8: // K6-2 + case 9: // K6-III + case 14: // K6-2+ / K6-III+ + strcpy( cpuinfo.x86Fam, "AMD K6" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown" ); + } + break; + case 6: + strcpy( cpuinfo.x86Fam, "AMD K7" ); + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown AMD CPU" ); + } + } + } + //capabilities + cpucaps.hasFloatingPointUnit = ( cpuinfo.x86Flags >> 0 ) & 1; + cpucaps.hasVirtual8086ModeEnhancements = ( cpuinfo.x86Flags >> 1 ) & 1; + cpucaps.hasDebuggingExtensions = ( cpuinfo.x86Flags >> 2 ) & 1; + cpucaps.hasPageSizeExtensions = ( cpuinfo.x86Flags >> 3 ) & 1; + cpucaps.hasTimeStampCounter = ( cpuinfo.x86Flags >> 4 ) & 1; + cpucaps.hasModelSpecificRegisters = ( cpuinfo.x86Flags >> 5 ) & 1; + cpucaps.hasPhysicalAddressExtension = ( cpuinfo.x86Flags >> 6 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 7 ) & 1; + cpucaps.hasCOMPXCHG8BInstruction = ( cpuinfo.x86Flags >> 8 ) & 1; + cpucaps.hasAdvancedProgrammableInterruptController = ( cpuinfo.x86Flags >> 9 ) & 1; + cpucaps.hasSEPFastSystemCall = ( cpuinfo.x86Flags >> 11 ) & 1; + cpucaps.hasMemoryTypeRangeRegisters = ( cpuinfo.x86Flags >> 12 ) & 1; + cpucaps.hasPTEGlobalFlag = ( cpuinfo.x86Flags >> 13 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 14 ) & 1; + cpucaps.hasConditionalMoveAndCompareInstructions = ( cpuinfo.x86Flags >> 15 ) & 1; + cpucaps.hasFGPageAttributeTable = ( cpuinfo.x86Flags >> 16 ) & 1; + cpucaps.has36bitPageSizeExtension = ( cpuinfo.x86Flags >> 17 ) & 1; + cpucaps.hasProcessorSerialNumber = ( cpuinfo.x86Flags >> 18 ) & 1; + cpucaps.hasCFLUSHInstruction = ( cpuinfo.x86Flags >> 19 ) & 1; + cpucaps.hasDebugStore = ( cpuinfo.x86Flags >> 21 ) & 1; + cpucaps.hasACPIThermalMonitorAndClockControl = ( cpuinfo.x86Flags >> 22 ) & 1; + cpucaps.hasMultimediaExtensions = ( cpuinfo.x86Flags >> 23 ) & 1; //mmx + cpucaps.hasFastStreamingSIMDExtensionsSaveRestore = ( cpuinfo.x86Flags >> 24 ) & 1; + cpucaps.hasStreamingSIMDExtensions = ( cpuinfo.x86Flags >> 25 ) & 1; //sse + cpucaps.hasStreamingSIMD2Extensions = ( cpuinfo.x86Flags >> 26 ) & 1; //sse2 + cpucaps.hasSelfSnoop = ( cpuinfo.x86Flags >> 27 ) & 1; + cpucaps.hasHyperThreading = ( cpuinfo.x86Flags >> 28 ) & 1; + cpucaps.hasThermalMonitor = ( cpuinfo.x86Flags >> 29 ) & 1; + cpucaps.hasIntel64BitArchitecture = ( cpuinfo.x86Flags >> 30 ) & 1; + //that is only for AMDs + cpucaps.hasMultimediaExtensionsExt = ( cpuinfo.x86EFlags >> 22 ) & 1; //mmx2 + cpucaps.hasAMD64BitArchitecture = ( cpuinfo.x86EFlags >> 29 ) & 1; //64bit cpu + cpucaps.has3DNOWInstructionExtensionsExt = ( cpuinfo.x86EFlags >> 30 ) & 1; //3dnow+ + cpucaps.has3DNOWInstructionExtensions = ( cpuinfo.x86EFlags >> 31 ) & 1; //3dnow + cpuinfo.cpuspeed = (u32 )(CPUSpeedHz( 1000 ) / 1000000); +} diff --git a/x86/ix86/ix86_fpu.c b/x86/ix86/ix86_fpu.c new file mode 100644 index 0000000000..98034a531d --- /dev/null +++ b/x86/ix86/ix86_fpu.c @@ -0,0 +1,269 @@ +#include +#include +#include "ix86.h" + +/********************/ +/* FPU instructions */ +/********************/ + +/* fild m32 to fpu reg stack */ +void FILD32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fistp m32 from fpu reg stack */ +void FISTP32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fld m32 to fpu reg stack */ +void FLD32( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// fld st(i) +void FLD(int st) { write16(0xc0d9+(st<<8)); } + +void FLD1() { write16(0xe8d9); } +void FLDL2E() { write16(0xead9); } + +/* fst m32 from fpu reg stack */ +void FST32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* fstp m32 from fpu reg stack */ +void FSTP32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// fstp st(i) +void FSTP(int st) { write16(0xd8dd+(st<<8)); } + +/* fldcw fpu control word from m16 */ +void FLDCW( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fnstcw fpu control word to m16 */ +void FNSTCW( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x7, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void FNSTSWtoAX( void ) +{ + write16( 0xE0DF ); +} + +void FXAM() +{ + write16(0xe5d9); +} + +void FDECSTP() { write16(0xf6d9); } +void FRNDINT() { write16(0xfcd9); } +void FXCH(int st) { write16(0xc8d9+(st<<8)); } +void F2XM1() { write16(0xf0d9); } +void FSCALE() { write16(0xfdd9); } + +/* fadd ST(src) to fpu reg stack ST(0) */ +void FADD32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC0 + src ); +} + +/* fadd ST(0) to fpu reg stack ST(src) */ +void FADD320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC0 + src ); +} + +/* fsub ST(src) to fpu reg stack ST(0) */ +void FSUB32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xE0 + src ); +} + +/* fsub ST(0) to fpu reg stack ST(src) */ +void FSUB320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xE8 + src ); +} + +/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ +void FSUBP( void ) +{ + write8( 0xDE ); + write8( 0xE9 ); +} + +/* fmul ST(src) to fpu reg stack ST(0) */ +void FMUL32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC8 + src ); +} + +/* fmul ST(0) to fpu reg stack ST(src) */ +void FMUL320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC8 + src ); +} + +/* fdiv ST(src) to fpu reg stack ST(0) */ +void FDIV32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xF0 + src ); +} + +/* fdiv ST(0) to fpu reg stack ST(src) */ +void FDIV320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xF8 + src ); +} + +void FDIV320toRP( x86IntRegType src ) +{ + write8( 0xDE ); + write8( 0xF8 + src ); +} + +/* fadd m32 to fpu reg stack */ +void FADD32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fsub m32 to fpu reg stack */ +void FSUB32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fmul m32 to fpu reg stack */ +void FMUL32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x1, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fdiv m32 to fpu reg stack */ +void FDIV32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fabs fpu reg stack */ +void FABS( void ) +{ + write16( 0xE1D9 ); +} + +/* fsqrt fpu reg stack */ +void FSQRT( void ) +{ + write16( 0xFAD9 ); +} + +void FPATAN(void) { write16(0xf3d9); } +void FSIN(void) { write16(0xfed9); } + +/* fchs fpu reg stack */ +void FCHS( void ) +{ + write16( 0xE0D9 ); +} + +/* fcomi st, st(i) */ +void FCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xF0 + src ); +} + +/* fcomip st, st(i) */ +void FCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xF0 + src ); +} + +/* fucomi st, st(i) */ +void FUCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xE8 + src ); +} + +/* fucomip st, st(i) */ +void FUCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xE8 + src ); +} + +/* fcom m32 to fpu reg stack */ +void FCOM32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fcomp m32 to fpu reg stack */ +void FCOMP32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +#define FCMOV32( low, high ) \ + { \ + write8( low ); \ + write8( high + from ); \ + } + +void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } +void FCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } +void FCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } +void FCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } +void FCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } +void FCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } +void FCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } +void FCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } diff --git a/x86/ix86/ix86_mmx.c b/x86/ix86/ix86_mmx.c new file mode 100644 index 0000000000..0f484bac4e --- /dev/null +++ b/x86/ix86/ix86_mmx.c @@ -0,0 +1,632 @@ + +#include "ix86.h" + +#include + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x6F0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movq r64 to m64 */ +void MOVQRtoM( u32 to, x86MMXRegType from ) +{ + write16( 0x7F0F ); + ModRM( 0, from, DISP32 ); + write32(MEMADDR(to, 4)); +} + +/* pand r64 to r64 */ +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDB0F ); + ModRM( 3, to, from ); +} + +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDF0F ); + ModRM( 3, to, from ); +} + +/* por r64 to r64 */ +void PORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEB0F ); + ModRM( 3, to, from ); +} + +/* pxor r64 to r64 */ +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEF0F ); + ModRM( 3, to, from ); +} + +/* psllq r64 to r64 */ +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF30F ); + ModRM( 3, to, from ); +} + +/* psllq m64 to r64 */ +void PSLLQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xF30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psllq imm8 to r64 */ +void PSLLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 6, to); + write8( from ); +} + +/* psrlq r64 to r64 */ +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD30F ); + ModRM( 3, to, from ); +} + +/* psrlq m64 to r64 */ +void PSRLQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xD30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psrlq imm8 to r64 */ +void PSRLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 2, to); + write8( from ); +} + +/* paddusb r64 to r64 */ +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDC0F ); + ModRM( 3, to, from ); +} + +/* paddusb m64 to r64 */ +void PADDUSBMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddusw r64 to r64 */ +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDD0F ); + ModRM( 3, to, from ); +} + +/* paddusw m64 to r64 */ +void PADDUSWMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddb r64 to r64 */ +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFC0F ); + ModRM( 3, to, from ); +} + +/* paddb m64 to r64 */ +void PADDBMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddw r64 to r64 */ +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFD0F ); + ModRM( 3, to, from ); +} + +/* paddw m64 to r64 */ +void PADDWMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddd r64 to r64 */ +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFE0F ); + ModRM( 3, to, from ); +} + +/* paddd m64 to r64 */ +void PADDDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* emms */ +void EMMS( void ) +{ + write16( 0x770F ); +} + +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEC0F ); + ModRM( 3, to, from ); +} + +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xED0F ); + ModRM( 3, to, from ); +} + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xD40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD40F ); + ModRM( 3, to, from ); +} + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE80F ); + ModRM( 3, to, from ); +} + +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE90F ); + ModRM( 3, to, from ); +} + + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF80F ); + ModRM( 3, to, from ); +} + +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF90F ); + ModRM( 3, to, from ); +} + +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFA0F ); + ModRM( 3, to, from ); +} + +void PSUBDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFA0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD80F ); + ModRM( 3, to, from ); +} + +void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD90F ); + ModRM( 3, to, from ); +} + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFB0F ); + ModRM( 3, to, from ); +} + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xF40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF40F ); + ModRM( 3, to, from ); +} + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x740F ); + ModRM( 3, to, from ); +} + +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x750F ); + ModRM( 3, to, from ); +} + +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x760F ); + ModRM( 3, to, from ); +} + +void PCMPEQDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x760F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x640F ); + ModRM( 3, to, from ); +} + +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x650F ); + ModRM( 3, to, from ); +} + +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x660F ); + ModRM( 3, to, from ); +} + +void PCMPGTDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x660F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSRLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD20F ); + ModRM( 3, to, from ); +} + +void PSLLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF20F ); + ModRM( 3, to, from ); +} + +void PSRAWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE20F ); + ModRM( 3, to, from ); +} + +/* por m64 to r64 */ +void PORMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xEB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pxor m64 to r64 */ +void PXORMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xEF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pand m64 to r64 */ +void PANDMtoR( x86MMXRegType to, u32 from ) +{ + //u64 rip = (u64)x86Ptr + 7; + write16( 0xDB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PANDNMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6A0F ); + ModRM( 3, to, from ); +} + +void PUNPCKHDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x6A0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x620F ); + ModRM( 3, to, from ); +} + +void PUNPCKLDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x620F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOVQ64ItoR( x86MMXRegType reg, u64 i ) +{ + MOVQMtoR( reg, ( u32 )(x86Ptr) + 2 + 7 ); + JMP8( 8 ); + write64( i ); +} + +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6F0F ); + ModRM( 3, to, from ); +} + +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6F0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7F0F ); + + if( offset < 128 ) { + ModRM( 1, from , to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movd m32 to r64 */ +void MOVDMtoMMX( x86MMXRegType to, u32 from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movd r64 to m32 */ +void MOVDMMXtoM( u32 to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 3, to, from ); +} + +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, from ); +} + +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6E0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 3, from, to ); +} + +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, to ); + if( to >= 4 ) { + // no idea why + assert( to == ESP ); + write8(0x24); + } + +} + +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7E0F ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///* movd r32 to r64 */ +//void MOVD32MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x6E0F ); +// ModRM( 3, to, from ); +//} +// +///* movq r64 to r32 */ +//void MOVD64MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x7E0F ); +// ModRM( 3, from, to ); +//} + +// untested +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x630F ); + ModRM( 3, to, from ); +} + +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x6B0F ); + ModRM( 3, to, from ); +} + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) +{ + write16( 0xD70F ); + ModRM( 3, to, from ); +} + +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) +{ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0xc40f ); + ModRM( 3, to, from ); + write8( imm8 ); +} + +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) +{ + write16(0x700f); + ModRM( 3, to, from ); + write8(imm8); +} + +void PSHUFWMtoR(x86MMXRegType to, u32 from, u8 imm8) +{ + write16( 0x700f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); + write8(imm8); +} + +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) +{ + write16(0xf70f); + ModRM( 3, to, from ); +} diff --git a/x86/ix86/ix86_sse.c b/x86/ix86/ix86_sse.c new file mode 100644 index 0000000000..249f08be16 --- /dev/null +++ b/x86/ix86/ix86_sse.c @@ -0,0 +1,1540 @@ + +#include "ix86.h" +__declspec(align(16)) unsigned int p[4],p2[4]; +__declspec(align(16)) float f[4]; + + +XMMSSEType g_xmmtypes[XMMREGS] = {0}; + +/********************/ +/* SSE instructions */ +/********************/ + +#define SSEMtoR( code, overb ) \ + if (to > 7) Rex(1, to >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSERtoM( code, overb ) \ + if (from > 7) Rex(1, from >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSE_SS_MtoR( code, overb ) \ + write8( 0xf3 ); \ + if (to > 7) Rex(1, to >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSE_SS_RtoM( code, overb ) \ + write8( 0xf3 ); \ + if (from > 7) Rex(1, from >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSERtoR( code ) \ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define SSEMtoR66( code ) \ + write8( 0x66 ); \ + SSEMtoR( code, 0 ); + +#define SSERtoM66( code ) \ + write8( 0x66 ); \ + SSERtoM( code, 0 ); + +#define SSERtoR66( code ) \ + write8( 0x66 ); \ + SSERtoR( code ); + +#define _SSERtoR66( code ) \ + write8( 0x66 ); \ + if (to > 7 || from > 7) Rex(1, from >> 3, 0, to >> 3); \ + write16( code ); \ + ModRM( 3, from, to ); + +#define SSE_SS_RtoR( code ) \ + write8( 0xf3 ); \ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define CMPPSMtoR( op ) \ + SSEMtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPPSRtoR( op ) \ + SSERtoR( 0xc20f ); \ + write8( op ); + +#define CMPSSMtoR( op ) \ + SSE_SS_MtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPSSRtoR( op ) \ + SSE_SS_RtoR( 0xc20f ); \ + write8( op ); + + + + + +/* movups [r32][r32*scale] to xmm1 */ +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups xmm1 to [r32][r32*scale] */ +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups [r32] to r32 */ +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + ModRM( 0, to, from ); +} + +/* movups r32 to [r32] */ +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x110f ); + ModRM( 0, from, to ); +} + +/* movlps [r32] to r32 */ +void SSE_MOVLPSRmtoR( x86MMXRegType to, x86IntRegType from ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x120f ); + ModRM( 0, to, from ); +} + +void SSE_MOVLPSRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x120f ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movaps r32 to [r32] */ +void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x130f ); + ModRM( 0, from, to ); +} + +void SSE_MOVLPSRtoRmOffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x130f ); + ModRM( 2, from, to ); + write32(offset); +} + +/* movaps [r32][r32*scale] to xmm1 */ +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movaps xmm1 to [r32][r32*scale] */ +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +// movaps [r32+offset] to r32 +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x280f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movaps r32 to [r32+offset] +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x290f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +// movdqa [r32+offset] to r32 +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write8(0x66); + write16( 0x6f0f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movdqa r32 to [r32+offset] +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write8(0x66); + write16( 0x7f0f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +// movups [r32+offset] to r32 +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movups r32 to [r32+offset] +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x110f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +//**********************************************************************************/ +//MOVAPS: Move aligned Packed Single Precision FP values * +//********************************************************************************** +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x280f, 0 ); } +void SSE_MOVAPS_XMM_to_M128( u32 to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); } +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x280f ); } + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x100f, 0 ); } +void SSE_MOVUPS_XMM_to_M128( u32 to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); } + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVSD_XMM_to_XMM(to, from); + else { + write8(0xf2); + SSERtoR( 0x100f); + } +} + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, u32 from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_M64_to_XMM(to, from); + else { + write8(0xf3); SSEMtoR( 0x7e0f, 0); + } +} + +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_XMM_to_XMM(to, from); + else { + write8(0xf3); SSERtoR( 0x7e0f); + } +} + +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVLPS_XMM_to_M64(to, from); + else { + SSERtoM66(0xd60f); + } +} + +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVDQ2Q_XMM_to_MM(to, from); + else { + write8(0xf2); + SSERtoR( 0xd60f); + } +} +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ2DQ_MM_to_XMM(to, from); + else { + write8(0xf3); + SSERtoR( 0xd60f); + } +} + +//**********************************************************************************/ +//MOVSS: Move Scalar Single-Precision FP value * +//********************************************************************************** +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x100f, 0 ); } +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); } +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0xf3); write16(0x110f); + ModRM(0, from, to); +} + +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x100f ); } + +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write8(0xf3); write16( 0x100f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write8(0xf3); write16(0x110f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xf70f ); } +//**********************************************************************************/ +//MOVLPS: Move low Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x120f, 0 ); } +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); } + +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x120f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write16(0x130f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHPS: Move High Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x160f, 0 ); } +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); } + +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x160f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write16(0x170f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVLHPS: Moved packed Single-Precision FP low to high * +//********************************************************************************** +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x160f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHLPS: Moved packed Single-Precision FP High to Low * +//********************************************************************************** +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x120f ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDPS: Logical Bit-wise AND for Single FP * +//********************************************************************************** +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x540f, 0 ); } +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x540f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDNPS : Logical Bit-wise AND NOT of Single-precision FP values * +//********************************************************************************** +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x550f, 0 ); } +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x550f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RCPPS : Packed Single-Precision FP Reciprocal * +//********************************************************************************** +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x530f ); } +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x530f, 0 ); } + +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x530f); } +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR(0x530f, 0); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ORPS : Bit-wise Logical OR of Single-Precision FP Data * +//********************************************************************************** +void SSE_ORPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x560f, 0 ); } +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x560f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//XORPS : Bitwise Logical XOR of Single-Precision FP Values * +//********************************************************************************** +void SSE_XORPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x570f, 0 ); } +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x570f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDPS : ADD Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x580f, 0 ); } +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x580f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDSS : ADD Scalar Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x580f, 0 ); } +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x580f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBPS: Packed Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5c0f, 0 ); } +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5c0f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBSS : Scalar Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5c0f, 0 ); } +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5c0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULPS : Packed Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x590f, 0 ); } +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULSS : Scalar Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x590f, 0 ); } +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Packed Single-Precission FP compare (CMPccPS) * +//********************************************************************************** +//missing SSE_CMPPS_I8_to_XMM +// SSE_CMPPS_M32_to_XMM +// SSE_CMPPS_XMM_to_XMM +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 0 ); } +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); } +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 1 ); } +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); } +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 2 ); } +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); } +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 3 ); } +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); } +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 4 ); } +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); } +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 5 ); } +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); } +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 6 ); } +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); } +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 7 ); } +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 7 ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Scalar Single-Precission FP compare (CMPccSS) * +//********************************************************************************** +//missing SSE_CMPSS_I8_to_XMM +// SSE_CMPSS_M32_to_XMM +// SSE_CMPSS_XMM_to_XMM +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 0 ); } +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); } +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 1 ); } +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); } +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 2 ); } +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); } +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 3 ); } +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); } +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 4 ); } +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); } +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 5 ); } +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); } +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 6 ); } +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); } +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 7 ); } +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); } + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, u32 from ) +{ + write16( 0x2e0f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + write16( 0x2e0f ); + ModRM( 3, to, from ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x520f, 0 ); } +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x520f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTSS : Scalar Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x520f, 0 ); } +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x520f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTPS : Packed Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x510f, 0 ); } +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x510f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTSS : Scalar Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x510f, 0 ); } +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x510f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXPS: Return Packed Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5f0f, 0 ); } +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXSS: Return Scalar Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5f0f, 0 ); } +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion * +//********************************************************************************** +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x2a0f, 0 ); } +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { SSERtoR( 0x2a0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPS2PI: Packed Single FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, u32 from ) { SSEMtoR( 0x2d0f, 0 ); } +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); } + +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, u32 from) { write8(0xf3); SSEMtoR(0x2c0f, 0); } +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) +{ + write8(0xf3); + write16(0x2c0f); + ModRM(3, to, from); +} + +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x2a0f, 0); } +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) +{ + write8(0xf3); + write16(0x2a0f); + ModRM(3, to, from); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion * +//********************************************************************************** +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5b0f, 0 ); } +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5b0f ); } + +//**********************************************************************************/ +//CVTPS2DQ: Packed Single Precision FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0x5b0f ); } +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINPS: Return Packed Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5d0f, 0 ); } +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5d0f ); } + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINSS: Return Scalar Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5d0f, 0 ); } +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMAXSW: Packed Signed Integer Word Maximum * +//********************************************************************************** +//missing + // SSE_PMAXSW_M64_to_MM +// SSE2_PMAXSW_M128_to_XMM +// SSE2_PMAXSW_XMM_to_XMM +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEE0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMINSW: Packed Signed Integer Word Minimum * +//********************************************************************************** +//missing + // SSE_PMINSW_M64_to_MM +// SSE2_PMINSW_M128_to_XMM +// SSE2_PMINSW_XMM_to_XMM +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEA0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SHUFPS: Shuffle Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR( 0xC60F ); write8( imm8 ); } +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); } + +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset, u8 imm8 ) +{ + write16(0xc60f); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } + write8(imm8); +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSHUFD: Shuffle Packed DoubleWords * +//********************************************************************************** +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_PSHUFD_XMM_to_XMM(to, from, imm8); + } + else { + SSERtoR66( 0x700F ); + write8( imm8 ); + } +} +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { SSEMtoR66( 0x700F ); write8( imm8 ); } + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF2); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { write8(0xF2); SSEMtoR(0x700F, 1); write8(imm8); } +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF3); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { write8(0xF3); SSEMtoR(0x700F, 1); write8(imm8); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR(0x140f, 0); } +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x140F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKHPS: Unpack and Interleave High Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR(0x150f, 0); } +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x150F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVPS : Packed Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5e0F, 0 ); } +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5e0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVSS : Scalar Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5e0F, 0 ); } +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5e0F ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//STMXCSR : Store Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_STMXCSR( u32 from ) { + write16( 0xAE0F ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//LDMXCSR : Load Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_LDMXCSR( u32 from ) { + write16( 0xAE0F ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PADDB,PADDW,PADDD : Add Packed Integers * +//********************************************************************************** +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFC0F ); } +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFC0F ); } +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); } +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFD0F ); } +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); } +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFE0F ); } + +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); } +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, u32 from ) { SSEMtoR66( 0xD40F ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x640F ); } +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x640F ); } +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); } +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x650F ); } +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); } +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x660F ); } +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); } +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x740F ); } +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); } +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x750F ); } +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_XMM_to_XMM(to, from); + } + else { + SSERtoR66( 0x760F ); + } +} + +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, u32 from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_M128_to_XMM(to, from); + } + else { + SSEMtoR66( 0x760F ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ){ SSERtoR66(0xC50F); write8( imm8 ); } +void SSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ){ SSERtoR66(0xC40F); write8( imm8 ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF80F ); } +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xF80F ); } +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); } +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xF90F ); } +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); } +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFA0F ); } +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); } +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFB0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66(0x6E0F); } +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_R_to_XMM(to, from); + } + else { + SSERtoR66(0x6E0F); + } +} + +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + write8(0x66); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0x6e0f ); + ModRM( 0, to, from ); +} + +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write8(0x66); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + + write16( 0x6e0f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { SSERtoM66(0x7E0F); } +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_R(to, from); + } + else { + _SSERtoR66(0x7E0F); + } +} + +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0x66); + write16( 0x7e0f ); + ModRM( 0, from, to ); +} + +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_RmOffset(to, from, offset); + } + else { + write8(0x66); + write16( 0x7e0f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); } +void SSE2_POR_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xEB0F ); } + +// logical and to &= from +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDB0F ); } +void SSE2_PAND_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDB0F ); } + +// to = (~to) & from +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDF0F ); } +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDF0F ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PXOR : SSE Bitwise XOR * +//********************************************************************************** +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEF0F ); } +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEF0F ) }; +/////////////////////////////////////////////////////////////////////////////////////// + +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, u32 from) {SSEMtoR66(0x6F0F); } +void SSE2_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ){SSERtoM66(0x7F0F);} +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSERtoR66(0x6F0F); } + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xF3); SSEMtoR(0x6F0F, 0); } +void SSE2_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from) { write8(0xF3); SSERtoM(0x7F0F, 0); } +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { write8(0xF3); SSERtoR(0x6F0F); } + +// shift right logical + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); } +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD10F); } +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD20F); } +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD20F); } +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD30F); } +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD30F); } +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 3 , to ); + write8( imm8 ); +} + +// shift right arithmetic + +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE10F); } +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xE10F); } +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE20F); } +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xE20F); } +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +// shift left logical + +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF10F); } +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF10F); } +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF20F); } +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF20F); } +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF30F); } +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF30F); } +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 7 , to ); + write8( imm8 ); +} + +// + +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEE0F ); } +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEE0F ); } + +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDE0F ); } +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xDE0F ); } + +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEA0F ); } +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEA0F ); } + +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDA0F ); } +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xDA0F ); } + +// + +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEC0F ); } +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEC0F ); } + +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xED0F ); } +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xED0F ); } + +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE80F ); } +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xE80F ); } + +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE90F ); } +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xE90F ); } + +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); } +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xD80F ); } +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); } +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xD90F ); } + +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); } +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDC0F ); } +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); } +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDD0F ); } + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x630F ); } +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x630F ); } +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); } +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6B0F ); } + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); } +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x670F ); } + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x600F ); } +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x600F ); } + +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); } +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x680F ); } + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); } +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x610F ); } +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); } +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x690F ); } + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); } +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x620F ); } +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); } +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6A0F ); } + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); } +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6C0F ); } + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); } +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6D0F ); } + +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); } +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xD50F ); } +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); } +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xE50F ); } + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); } +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xF40F ); } + +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0xD70F); } + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR(0x500F); } +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0x500F); } + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf2); SSERtoR( 0x7c0f ); } +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, u32 from){ write8(0xf2); SSEMtoR( 0x7c0f, 0 ); } + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x120f); } +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x120f, 0); } +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x160f); } +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x160f, 0); } + +// SSE-X +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQA_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoROffset(to, from, offset); + else SSE_MOVAPSRmtoROffset(to, from, offset); +} + +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRmOffset(to, from, offset); + else SSE_MOVAPSRtoRmOffset(to, from, offset); +} + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQU_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_M32_to_XMM(to, from); + else SSE_MOVSS_M32_to_XMM(to, from); +} + +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_M32(to, from); + else SSE_MOVSS_XMM_to_M32(to, from); +} + +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from); + else SSE_MOVSS_XMM_to_Rm(to, from); +} + +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_RmOffset_to_XMM(to, from, offset); + else SSE_MOVSS_RmOffset_to_XMM(to, from, offset); +} + +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_RmOffset(to, from, offset); + else SSE_MOVSS_XMM_to_RmOffset(to, from, offset); +} + +void SSEX_POR_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_POR_M128_to_XMM(to, from); + else SSE_ORPS_M128_to_XMM(to, from); +} + +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_POR_XMM_to_XMM(to, from); + else SSE_ORPS_XMM_to_XMM(to, from); +} + +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PXOR_M128_to_XMM(to, from); + else SSE_XORPS_M128_to_XMM(to, from); +} + +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PXOR_XMM_to_XMM(to, from); + else SSE_XORPS_XMM_to_XMM(to, from); +} + +void SSEX_PAND_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PAND_M128_to_XMM(to, from); + else SSE_ANDPS_M128_to_XMM(to, from); +} + +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PAND_XMM_to_XMM(to, from); + else SSE_ANDPS_XMM_to_XMM(to, from); +} + +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PANDN_M128_to_XMM(to, from); + else SSE_ANDNPS_M128_to_XMM(to, from); +} + +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PANDN_XMM_to_XMM(to, from); + else SSE_ANDNPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKLDQ_M128_to_XMM(to, from); + else SSE_UNPCKLPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKLDQ_XMM_to_XMM(to, from); + else SSE_UNPCKLPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKHDQ_M128_to_XMM(to, from); + else SSE_UNPCKHPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKHDQ_XMM_to_XMM(to, from); + else SSE_UNPCKHPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(to, from); + if( to != from ) SSE2_PSHUFD_XMM_to_XMM(to, to, 0x4e); + } + else { + SSE_MOVHLPS_XMM_to_XMM(to, from); + } +} + +// SSE2 emulation +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_SHUFPS_XMM_to_XMM(to, from, 0x4e); + SSE_SHUFPS_XMM_to_XMM(to, to, 0x4e); +} + +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, u32 from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE_MOVLPS_M64_to_XMM(to, from); +} + +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE2EMU_MOVSD_XMM_to_XMM(to, from); +} + +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + MOV32RmtoROffset(EAX, from, offset); + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, EAX); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} + +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, u32 offset ) +{ + SSE_MOVSS_XMM_to_M32((u32)p, from); + MOV32MtoR(EAX, (u32)p); + MOV32RtoRmOffset(to, EAX, offset); +} + +extern void SetMMXstate(); + +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + SSE_MOVLPS_XMM_to_M64((u32)p, from); + MOVQMtoR(to, (u32)p); + SetMMXstate(); +} + +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + MOVQRtoM((u32)p, from); + SSE_MOVLPS_M64_to_XMM(to, (u32)p); + SetMMXstate(); +} + +/****************************************************************************/ +/* SSE2 Emulated functions for SSE CPU's by kekko */ +/****************************************************************************/ +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { + MOV32ItoR(EAX, (u32)&p); + MOV32ItoR(EBX, (u32)&p2); + SSE_MOVUPSRtoRm(EAX, from); + + MOV32ItoR(ECX, (u32)imm8); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 2); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 4); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 6); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + SUB32ItoR(EBX, 12); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + MOV32ItoR(to, (u32)&p); + SSE_MOVUPSRtoRm(to, from); + MOV32RmtoR(to, to); +} + + +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { + MOV32ItoR(EAX, (u32)&f); + MOV32ItoR(EBX, (u32)&p2); + SSE_MOVUPSRtoRm(EAX, from); + + FLD32((u32)&f[0]); + FISTP32((u32)&p2[0]); + FLD32((u32)&f[1]); + FISTP32((u32)&p2[1]); + FLD32((u32)&f[2]); + FISTP32((u32)&p2[2]); + FLD32((u32)&f[3]); + FISTP32((u32)&p2[3]); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ) { + MOV32ItoR(EAX, (u32)&from); + MOV32ItoR(EBX, (u32)&f); + + FILD32((u32)from); + FSTP32((u32)&f[0]); + FILD32((u32)from+4); + FSTP32((u32)&f[1]); + FILD32((u32)from+8); + FSTP32((u32)&f[2]); + FILD32((u32)from+12); + FSTP32((u32)&f[3]); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { + MOV32ItoR(EAX, (u32)&p); + SSE_MOVUPSRtoRm(EAX, from); + MOV32RmtoR(EAX, EAX); + MOV32RtoM(to, EAX); +} + +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, from); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} diff --git a/x86/recCOP2.c b/x86/recCOP2.c new file mode 100644 index 0000000000..3e7334d2d4 --- /dev/null +++ b/x86/recCOP2.c @@ -0,0 +1,739 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#include +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "iVU0micro.h" +#include "iVUmicro.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// cycle cycles statusflag macflag clipflag +_vuopinfo g_cop2info = {0, 0, 1, 1, 1, 0, 0}; + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) +#define _Cc_ (cpuRegs.code & 0x03) + +#define REC_COP2_FUNC(f, delreg) \ + void f(); \ + void rec##f() { \ + SysPrintf("cop2 "#f" called\n"); \ + SetFPUstate(); \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_NOCONST); \ + CALLFunc((u32)f); \ + _freeX86regs(); \ + branch = 2; \ +} + +#define INTERPRETATE_COP2_FUNC(f) \ +void recV##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)V##f); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0MS(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0CLIP(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + + +void rec_C2UNK() +{ + SysPrintf("Cop2 bad opcode:%x\n",cpuRegs.code); +} + +void _vuRegs_C2UNK(VURegs * VU, _VURegsNum *VUregsn) +{ + SysPrintf("Cop2 bad _vuRegs code:%x\n",cpuRegs.code); +} + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn); + +void (*recCOP2t[32])(); +void (*recCOP2_BC2t[32])(); +void (*recCOP2SPECIAL1t[64])(); +void (*recCOP2SPECIAL2t[128])(); + +void recCOP2(); +void recCOP2_SPECIAL(); +void recCOP2_BC2(); +void recCOP2_SPECIAL2(); + +extern void _vu0WaitMicro(); + +static void recCFC2() +{ + int mmreg; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteGPRtoXMMreg(_Rt_, 2); + + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE)) >= 0 ) { + + if( _Fs_ >= 16 ) { + MOVDMtoMMX(mmreg, (u32)&VU0.VI[ _Fs_ ].UL); + + if( EEINST_ISLIVE1(_Rt_) ) { + _signExtendGPRtoMMX(mmreg, _Rt_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + else { + MOVDMtoMMX(mmreg, (u32)&VU0.VI[ _Fs_ ].UL); + } + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&VU0.VI[ _Fs_ ].UL); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + if( _Fs_ < 16 ) { + // no sign extending + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1],0); + } + else { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + + _eeOnWriteReg(_Rt_, 1); +} + +static void recCTC2() +{ + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( GPR_IS_CONST1(_Rt_) ) { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + if( g_cpuConstRegs[_Rt_].UL[0] & 2 ) { + CALLFunc((u32)vu0ResetRegs); + } + + if( g_cpuConstRegs[_Rt_].UL[0] & 0x200 ) { + CALLFunc((u32)vu1ResetRegs); + } + + MOV16ItoM((u32)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c); + break; + + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + MOV32ItoM((u32)&VU1.VI[REG_TPC].UL, g_cpuConstRegs[_Rt_].UL[0]&0xffff); + PUSH32I(g_cpuConstRegs[_Rt_].UL[0]&0xffff); + CALLFunc((u32)vu1ExecMicro); // Execute VU1 Micro SubRoutine + ADD32ItoR(ESP,4); + + x86SetJ8( j8Ptr[0] ); + break; + default: + MOV32ItoM((u32)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + _eeMoveGPRtoR(EAX, _Rt_); + + TEST32ItoR(EAX,0x2); + j8Ptr[0] = JZ8(0); + CALLFunc((u32)vu0ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX,0x200); + j8Ptr[0] = JZ8(0); + CALLFunc((u32)vu1ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + AND32ItoR(EAX,0x0C0C); + MOV16RtoM((u32)&VU0.VI[REG_FBRST].UL,EAX); + break; + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + _eeMoveGPRtoR(EAX, _Rt_); + MOV16RtoM((u32)&VU1.VI[REG_TPC].UL,EAX); + + PUSH32R(EAX); + CALLFunc((u32)vu1ExecMicro); // Execute VU1 Micro SubRoutine + ADD32ItoR(ESP,4); + + x86SetJ8( j8Ptr[0] ); + break; + default: + _eeMoveGPRtoM((u32)&VU0.VI[_Fs_].UL,_Rt_); + break; + } + } +} + +static void recQMFC2(void) +{ + int t0reg, fsreg; + _xmmregs temp; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + + // could 'borrow' the reg + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_READ); + + if( fsreg >= 0 ) { + if( xmmregs[fsreg].mode & MODE_WRITE ) { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + SSEX_MOVDQA_XMM_to_XMM(t0reg, fsreg); + + // change regs + temp = xmmregs[t0reg]; + xmmregs[t0reg] = xmmregs[fsreg]; + xmmregs[fsreg] = temp; + } + else { + // swap regs + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + + xmmregs[fsreg] = xmmregs[t0reg]; + xmmregs[t0reg].inuse = 0; + } + } + else { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + SSE_MOVAPS_M128_to_XMM( t0reg, (u32)&VU0.VF[_Fs_].UD[0]); + } + + _clearNeededXMMregs(); +} + +static void recQMTC2() +{ + int mmreg, fsreg; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_WRITE); + + if( fsreg >= 0 ) { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + SSE_MOVAPS_XMM_to_XMM(fsreg, mmreg); + } + else { + // swap regs + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((u32)&cpuRegs.GPR.r[_Rt_], mmreg); + + xmmregs[mmreg] = xmmregs[fsreg]; + xmmregs[mmreg].mode = MODE_WRITE; + xmmregs[fsreg].inuse = 0; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((u32)&cpuRegs.GPR.r[_Rt_], mmreg); + + // swap regs + xmmregs[mmreg].type = XMMTYPE_VFREG; + xmmregs[mmreg].VU = 0; + xmmregs[mmreg].reg = _Fs_; + xmmregs[mmreg].mode = MODE_WRITE; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + fsreg = _allocVFtoXMMreg(&VU0, -1, _Fs_, MODE_WRITE); + + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(fsreg, mmreg); + SSE_MOVHPS_M64_to_XMM(fsreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + } + else { + + if( GPR_IS_CONST1( _Rt_ ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ) == -1 ); + _flushConstReg(_Rt_); + } + + SSE_MOVAPS_M128_to_XMM(fsreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + } + } + + _clearNeededXMMregs(); +} + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls) +{ + _vuRegsCOP22(&VU0, &pinst->vuregs); + if( !dostalls ) return; + + _recvuTestLowerStalls(&VU0, &pinst->vuregs); + + switch(VU0.code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU0.code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + pinst->vuregs.VIwrite |= (1<vuregs.VIwrite |= (1<vuregs.VIwrite & (1 << REG_CLIP_FLAG)) { + _recAddWriteBack(vucycle+4, 1<vuregs.VIwrite & (1 << REG_Q)) { + _recAddWriteBack(vucycle+pinst->vuregs.cycles, 1<cycle = vucycle; + _recvuAddLowerStalls(&VU0, &pinst->vuregs); + _recvuTestPipes(&VU0); + + vucycle++; +} + +////////////////////////////////////////////////////////////////////////// +// BC2: Instructions +////////////////////////////////////////////////////////////////////////// +REC_COP2_FUNC(BC2F, 0); +REC_COP2_FUNC(BC2T, 0); +REC_COP2_FUNC(BC2FL, 0); +REC_COP2_FUNC(BC2TL, 0); + +////////////////////////////////////////////////////////////////////////// +// Special1 instructions +////////////////////////////////////////////////////////////////////////// +//TODO: redirect all the opcodes to the ivu0micro same functions +REC_COP2_VU0(IADD); +REC_COP2_VU0(IADDI); +REC_COP2_VU0(ISUB); +REC_COP2_VU0(IOR); +REC_COP2_VU0(IAND); +REC_COP2_VU0MS(OPMSUB); +REC_COP2_VU0MS(MADDq); +REC_COP2_VU0MS(MADDi); +REC_COP2_VU0MS(MSUBq); +REC_COP2_VU0MS(MSUBi); +REC_COP2_VU0MS(SUBi); +REC_COP2_VU0MS(SUBq); +REC_COP2_VU0MS(MULi); +REC_COP2_VU0MS(MULq); +REC_COP2_VU0(MAXi); +REC_COP2_VU0(MINIi); +REC_COP2_VU0MS(MUL); +REC_COP2_VU0(MAX); +REC_COP2_VU0MS(MADD); +REC_COP2_VU0MS(MSUB); + +REC_COP2_VU0(MINIx); +REC_COP2_VU0(MINIy); +REC_COP2_VU0(MINIz); +REC_COP2_VU0(MINIw); + +REC_COP2_VU0(MAXx); +REC_COP2_VU0(MAXy); +REC_COP2_VU0(MAXz); +REC_COP2_VU0(MAXw); + +REC_COP2_VU0MS(MULx); +REC_COP2_VU0MS(MULy); +REC_COP2_VU0MS(MULz); +REC_COP2_VU0MS(MULw); + +REC_COP2_VU0MS(ADD); +REC_COP2_VU0MS(ADDi); +REC_COP2_VU0MS(ADDq); +REC_COP2_VU0MS(ADDx); +REC_COP2_VU0MS(ADDy); +REC_COP2_VU0MS(ADDz); +REC_COP2_VU0MS(ADDw); + +REC_COP2_VU0MS(SUBx); +REC_COP2_VU0MS(SUBy); +REC_COP2_VU0MS(SUBz); +REC_COP2_VU0MS(SUBw); + +REC_COP2_VU0MS(MADDx); +REC_COP2_VU0MS(MADDy); +REC_COP2_VU0MS(MADDz); +REC_COP2_VU0MS(MADDw); + +REC_COP2_VU0MS(MSUBx); +REC_COP2_VU0MS(MSUBy); +REC_COP2_VU0MS(MSUBz); +REC_COP2_VU0MS(MSUBw); + +REC_COP2_VU0MS(SUB); +REC_COP2_VU0(MINI); + +////////////////////////////////////////////////////////////////////////// +// Special2 instructions +////////////////////////////////////////////////////////////////////////// + +REC_COP2_VU0CLIP(CLIP); +REC_COP2_VU0(LQI); +REC_COP2_VU0(SQI); +REC_COP2_VU0(LQD); +REC_COP2_VU0(SQD); +REC_COP2_VU0(MTIR); +REC_COP2_VU0(MFIR); +REC_COP2_VU0(ILWR); +REC_COP2_VU0(ISWR); +REC_COP2_VU0(RINIT); +REC_COP2_VU0(RXOR); +REC_COP2_VU0(RNEXT); +REC_COP2_VU0(RGET); + +REC_COP2_VU0(ITOF0); +REC_COP2_VU0(ITOF4); +REC_COP2_VU0(ITOF12); +REC_COP2_VU0(ITOF15); +REC_COP2_VU0(FTOI0); +REC_COP2_VU0(FTOI4); +REC_COP2_VU0(FTOI12); +REC_COP2_VU0(FTOI15); +REC_COP2_VU0MS(MADDA); +REC_COP2_VU0MS(MSUBA); +REC_COP2_VU0MS(MADDAi); +REC_COP2_VU0MS(MADDAq); +REC_COP2_VU0MS(MADDAx); +REC_COP2_VU0MS(MADDAy); +REC_COP2_VU0MS(MADDAz); +REC_COP2_VU0MS(MADDAw); +REC_COP2_VU0MS(MSUBAi); +REC_COP2_VU0MS(MSUBAq); +REC_COP2_VU0MS(MSUBAx); +REC_COP2_VU0MS(MSUBAy); +REC_COP2_VU0MS(MSUBAz); +REC_COP2_VU0MS(MSUBAw); +REC_COP2_VU0MS(ADDAi); +REC_COP2_VU0MS(ADDA); +REC_COP2_VU0MS(SUBA); +REC_COP2_VU0MS(MULA); +REC_COP2_VU0MS(ADDAq); +REC_COP2_VU0MS(ADDAx); +REC_COP2_VU0MS(ADDAy); +REC_COP2_VU0MS(ADDAz); +REC_COP2_VU0MS(ADDAw); +REC_COP2_VU0MS(SUBAi); +REC_COP2_VU0MS(SUBAq); +REC_COP2_VU0MS(SUBAx); +REC_COP2_VU0MS(SUBAy); +REC_COP2_VU0MS(SUBAz); +REC_COP2_VU0MS(SUBAw); +REC_COP2_VU0MS(MULAi); +REC_COP2_VU0MS(MULAq); +REC_COP2_VU0MS(MULAx); +REC_COP2_VU0MS(MULAy); +REC_COP2_VU0MS(MULAz); +REC_COP2_VU0MS(MULAw); +REC_COP2_VU0MS(OPMULA); +REC_COP2_VU0(MOVE); +REC_COP2_VU0MS(DIV); +REC_COP2_VU0MS(SQRT); +REC_COP2_VU0MS(RSQRT); +REC_COP2_VU0(MR32); +REC_COP2_VU0(ABS); + +void recVNOP(){} +void recVWAITQ(){} +INTERPRETATE_COP2_FUNC(CALLMS); +INTERPRETATE_COP2_FUNC(CALLMSR); + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn); + +// information +void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xf; +} + +void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIread = 1<<_Fs_; +} + +void _vuRegsQMTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFwrite = _Fs_; + VUregsn->VFwxyzw= 0xf; +} + +void _vuRegsCTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIwrite = 1<<_Fs_; +} + +void (*_vuRegsCOP2t[32])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegs_C2UNK, _vuRegsQMFC2, _vuRegsCFC2, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsQMTC2, _vuRegsCTC2, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, +}; + +void (*_vuRegsCOP2SPECIAL1t[64])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDx, _vuRegsADDy, _vuRegsADDz, _vuRegsADDw, _vuRegsSUBx, _vuRegsSUBy, _vuRegsSUBz, _vuRegsSUBw, + _vuRegsMADDx, _vuRegsMADDy, _vuRegsMADDz, _vuRegsMADDw, _vuRegsMSUBx, _vuRegsMSUBy, _vuRegsMSUBz, _vuRegsMSUBw, + _vuRegsMAXx, _vuRegsMAXy, _vuRegsMAXz, _vuRegsMAXw, _vuRegsMINIx, _vuRegsMINIy, _vuRegsMINIz, _vuRegsMINIw, + _vuRegsMULx, _vuRegsMULy, _vuRegsMULz, _vuRegsMULw, _vuRegsMULq, _vuRegsMAXi, _vuRegsMULi, _vuRegsMINIi, + _vuRegsADDq, _vuRegsMADDq, _vuRegsADDi, _vuRegsMADDi, _vuRegsSUBq, _vuRegsMSUBq, _vuRegsSUBi, _vuRegsMSUBi, + _vuRegsADD, _vuRegsMADD, _vuRegsMUL, _vuRegsMAX, _vuRegsSUB, _vuRegsMSUB, _vuRegsOPMSUB, _vuRegsMINI, + _vuRegsIADD, _vuRegsISUB, _vuRegsIADDI, _vuRegs_C2UNK, _vuRegsIAND, _vuRegsIOR, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2, +}; + +void (*_vuRegsCOP2SPECIAL2t[128])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDAx ,_vuRegsADDAy ,_vuRegsADDAz ,_vuRegsADDAw ,_vuRegsSUBAx ,_vuRegsSUBAy ,_vuRegsSUBAz ,_vuRegsSUBAw, + _vuRegsMADDAx ,_vuRegsMADDAy ,_vuRegsMADDAz ,_vuRegsMADDAw ,_vuRegsMSUBAx ,_vuRegsMSUBAy ,_vuRegsMSUBAz ,_vuRegsMSUBAw, + _vuRegsITOF0 ,_vuRegsITOF4 ,_vuRegsITOF12 ,_vuRegsITOF15 ,_vuRegsFTOI0 ,_vuRegsFTOI4 ,_vuRegsFTOI12 ,_vuRegsFTOI15, + _vuRegsMULAx ,_vuRegsMULAy ,_vuRegsMULAz ,_vuRegsMULAw ,_vuRegsMULAq ,_vuRegsABS ,_vuRegsMULAi ,_vuRegsCLIP, + _vuRegsADDAq ,_vuRegsMADDAq ,_vuRegsADDAi ,_vuRegsMADDAi ,_vuRegsSUBAq ,_vuRegsMSUBAq ,_vuRegsSUBAi ,_vuRegsMSUBAi, + _vuRegsADDA ,_vuRegsMADDA ,_vuRegsMULA ,_vuRegs_C2UNK ,_vuRegsSUBA ,_vuRegsMSUBA ,_vuRegsOPMULA ,_vuRegsNOP, + _vuRegsMOVE ,_vuRegsMR32 ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegsLQI ,_vuRegsSQI ,_vuRegsLQD ,_vuRegsSQD, + _vuRegsDIV ,_vuRegsSQRT ,_vuRegsRSQRT ,_vuRegsWAITQ ,_vuRegsMTIR ,_vuRegsMFIR ,_vuRegsILWR ,_vuRegsISWR, + _vuRegsRNEXT ,_vuRegsRGET ,_vuRegsRINIT ,_vuRegsRXOR ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, +}; + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2t[_Rs_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2SPECIAL1t[_Funct_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn) +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + _vuRegsCOP2SPECIAL2t[opc](VU, VUregsn); +} + +// recompilation +void (*recCOP2t[32])() = { + rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK, + recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, +}; + +void (*recCOP2_BC2t[32])() = { + recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, +}; + +void (*recCOP2SPECIAL1t[64])() = { + recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw, + recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw, + recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw, + recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi, + recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi, + recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI, + recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK, + recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2, +}; + +void (*recCOP2SPECIAL2t[128])() = { + recVADDAx ,recVADDAy ,recVADDAz ,recVADDAw ,recVSUBAx ,recVSUBAy ,recVSUBAz ,recVSUBAw, + recVMADDAx ,recVMADDAy ,recVMADDAz ,recVMADDAw ,recVMSUBAx ,recVMSUBAy ,recVMSUBAz ,recVMSUBAw, + recVITOF0 ,recVITOF4 ,recVITOF12 ,recVITOF15 ,recVFTOI0 ,recVFTOI4 ,recVFTOI12 ,recVFTOI15, + recVMULAx ,recVMULAy ,recVMULAz ,recVMULAw ,recVMULAq ,recVABS ,recVMULAi ,recVCLIP, + recVADDAq ,recVMADDAq ,recVADDAi ,recVMADDAi ,recVSUBAq ,recVMSUBAq ,recVSUBAi ,recVMSUBAi, + recVADDA ,recVMADDA ,recVMULA ,rec_C2UNK ,recVSUBA ,recVMSUBA ,recVOPMULA ,recVNOP, + recVMOVE ,recVMR32 ,rec_C2UNK ,rec_C2UNK ,recVLQI ,recVSQI ,recVLQD ,recVSQD, + recVDIV ,recVSQRT ,recVRSQRT ,recVWAITQ ,recVMTIR ,recVMFIR ,recVILWR ,recVISWR, + recVRNEXT ,recVRGET ,recVRINIT ,recVRXOR ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, +}; + +void recCOP22() +{ + cinfo = &g_cop2info; + g_VUregs = &g_pCurInstInfo->vuregs; + VU0.code = cpuRegs.code; + g_pCurInstInfo->vuregs.pipe = 0xff; // to notify eeVURecompileCode that COP2 + recCOP2t[_Rs_](); + _freeX86regs(); +} + +void recCOP2_SPECIAL() +{ + recCOP2SPECIAL1t[_Funct_](); +} + +void recCOP2_BC2() +{ + recCOP2_BC2t[_Rt_](); +} + +void recCOP2_SPECIAL2() +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + recCOP2SPECIAL2t[opc](); +} diff --git a/zlib/ChangeLog b/zlib/ChangeLog new file mode 100644 index 0000000000..85b82536b9 --- /dev/null +++ b/zlib/ChangeLog @@ -0,0 +1,722 @@ + + ChangeLog file for zlib + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id: ChangeLog,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/zlib/README b/zlib/README new file mode 100644 index 0000000000..718aab288a --- /dev/null +++ b/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.1 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.1 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/zlib/adler32.c b/zlib/adler32.c new file mode 100644 index 0000000000..bc0842f01b --- /dev/null +++ b/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/zlib/compress.c b/zlib/compress.c new file mode 100644 index 0000000000..e7ea2c518b --- /dev/null +++ b/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/zlib/crc32.c b/zlib/crc32.c new file mode 100644 index 0000000000..aa8b984a34 --- /dev/null +++ b/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/zlib/crc32.h b/zlib/crc32.h new file mode 100644 index 0000000000..5de49bc978 --- /dev/null +++ b/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/zlib/deflate.c b/zlib/deflate.c new file mode 100644 index 0000000000..efe7b63aba --- /dev/null +++ b/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/zlib/deflate.h b/zlib/deflate.h new file mode 100644 index 0000000000..26775e9d12 --- /dev/null +++ b/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/zlib/gzio.c b/zlib/gzio.c new file mode 100644 index 0000000000..4cfd64fc45 --- /dev/null +++ b/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/zlib/infback.c b/zlib/infback.c new file mode 100644 index 0000000000..5cf5d22cf9 --- /dev/null +++ b/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/zlib/inffast.c b/zlib/inffast.c new file mode 100644 index 0000000000..63aa4402fc --- /dev/null +++ b/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/zlib/inffast.h b/zlib/inffast.h new file mode 100644 index 0000000000..614fa7877d --- /dev/null +++ b/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/zlib/inffixed.h b/zlib/inffixed.h new file mode 100644 index 0000000000..423d5c5b50 --- /dev/null +++ b/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/zlib/inflate.c b/zlib/inflate.c new file mode 100644 index 0000000000..71fe3ccd0e --- /dev/null +++ b/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/zlib/inflate.h b/zlib/inflate.h new file mode 100644 index 0000000000..b6965127b9 --- /dev/null +++ b/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/zlib/inftrees.c b/zlib/inftrees.c new file mode 100644 index 0000000000..55fd27b601 --- /dev/null +++ b/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/zlib/inftrees.h b/zlib/inftrees.h new file mode 100644 index 0000000000..1dbfe53a6a --- /dev/null +++ b/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/zlib/trees.c b/zlib/trees.c new file mode 100644 index 0000000000..d0bce9f2f1 --- /dev/null +++ b/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/zlib/trees.h b/zlib/trees.h new file mode 100644 index 0000000000..1ca868b848 --- /dev/null +++ b/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/zlib/uncompr.c b/zlib/uncompr.c new file mode 100644 index 0000000000..82ebef75f8 --- /dev/null +++ b/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/zlib/zconf.h b/zlib/zconf.h new file mode 100644 index 0000000000..b073c9e60d --- /dev/null +++ b/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/zlib/zlib.h b/zlib/zlib.h new file mode 100644 index 0000000000..d54ac9433f --- /dev/null +++ b/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/zlib/zutil.c b/zlib/zutil.c new file mode 100644 index 0000000000..db137f8a48 --- /dev/null +++ b/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/zlib/zutil.h b/zlib/zutil.h new file mode 100644 index 0000000000..e300f7c767 --- /dev/null +++ b/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */