diff options
Diffstat (limited to 'libpcsxcore')
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/cdriso.c | 2050 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/cdriso.h | 68 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/cdrom.c | 5014 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/cdrom.h | 242 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/debug.c | 2290 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/decode_xa.c | 734 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/disr3000a.c | 674 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/gpu.c | 372 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/gpu.h | 36 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86/iR3000A.c | 6030 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86/ix86.c | 3454 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86_64/iR3000A-64.c | 6050 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86_64/ix86-64.c | 6286 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86_64/ix86-64.h | 3552 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86_64/ix86_cpudetect.c | 984 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86_64/ix86_mmx.c | 1302 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ix86_64/ix86_sse.c | 2920 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/mdec.c | 1356 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/misc.c | 1498 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/plugins.c | 1678 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/plugins.h | 848 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ppc/pR3000A.c | 7086 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/ppf.c | 792 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psemu_plugin_defs.h | 570 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxbios.c | 5676 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxbios.h | 102 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxcommon.h | 384 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxcounters.c | 972 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxinterpreter.c | 2222 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxmem.c | 748 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/psxmem.h | 288 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/r3000a.c | 534 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/r3000a.h | 678 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/sio.c | 2656 | ||||
| -rwxr-xr-x[-rw-r--r--] | libpcsxcore/socket.c | 508 |
35 files changed, 35327 insertions, 35327 deletions
diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index 78f00bfb..d6867d64 100644..100755 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -1,1025 +1,1025 @@ -/***************************************************************************
- * Copyright (C) 2007 PCSX-df Team *
- * Copyright (C) 2009 Wei Mingzhi *
- * *
- * 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#include "psxcommon.h"
-#include "plugins.h"
-#include "cdrom.h"
-#include "cdriso.h"
-
-#ifdef _WIN32
-#include <process.h>
-#include <windows.h>
-#else
-#include <pthread.h>
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-
-static FILE *cdHandle = NULL;
-static FILE *cddaHandle = NULL;
-static FILE *subHandle = NULL;
-
-static boolean subChanMixed = FALSE;
-static boolean subChanRaw = FALSE;
-
-static unsigned char cdbuffer[CD_FRAMESIZE_RAW];
-static unsigned char subbuffer[SUB_FRAMESIZE];
-
-static unsigned char sndbuffer[CD_FRAMESIZE_RAW * 10];
-
-#define CDDA_FRAMETIME (1000 * (sizeof(sndbuffer) / CD_FRAMESIZE_RAW) / 75)
-
-
-#define MODE1_DATA_SIZE 2048
-
-static boolean isMode1ISO = FALSE;
-
-
-#ifdef _WIN32
-static HANDLE threadid;
-#else
-static pthread_t threadid;
-#endif
-static unsigned int initial_offset = 0;
-static volatile boolean playing = FALSE;
-static boolean cddaBigEndian = FALSE;
-static volatile unsigned int cddaCurOffset = 0;
-
-char* CALLBACK CDR__getDriveLetter(void);
-long CALLBACK CDR__configure(void);
-long CALLBACK CDR__test(void);
-void CALLBACK CDR__about(void);
-long CALLBACK CDR__setfilename(char *filename);
-long CALLBACK CDR__getStatus(struct CdrStat *stat);
-
-extern void *hCDRDriver;
-
-struct trackinfo {
- enum {DATA=1, CDDA} type;
- u8 start[3]; // MSF-format
- u8 length[3]; // MSF-format
-};
-
-#define MAXTRACKS 100 /* How many tracks can a CD hold? */
-
-static int numtracks = 0;
-static struct trackinfo ti[MAXTRACKS];
-
-// get a sector from a msf-array
-unsigned int msf2sec(char *msf) {
- return ((msf[0] * 60 + msf[1]) * 75) + msf[2];
-}
-
-void sec2msf(unsigned int s, char *msf) {
- msf[0] = s / 75 / 60;
- s = s - msf[0] * 75 * 60;
- msf[1] = s / 75;
- s = s - msf[1] * 75;
- msf[2] = s;
-}
-
-// divide a string of xx:yy:zz into m, s, f
-static void tok2msf(char *time, char *msf) {
- char *token;
-
- token = strtok(time, ":");
- if (token) {
- msf[0] = atoi(token);
- }
- else {
- msf[0] = 0;
- }
-
- token = strtok(NULL, ":");
- if (token) {
- msf[1] = atoi(token);
- }
- else {
- msf[1] = 0;
- }
-
- token = strtok(NULL, ":");
- if (token) {
- msf[2] = atoi(token);
- }
- else {
- msf[2] = 0;
- }
-}
-
-#ifndef _WIN32
-static long GetTickCount(void) {
- static time_t initial_time = 0;
- struct timeval now;
-
- gettimeofday(&now, NULL);
-
- if (initial_time == 0) {
- initial_time = now.tv_sec;
- }
-
- return (now.tv_sec - initial_time) * 1000L + now.tv_usec / 1000L;
-}
-#endif
-
-
-u16 *iso_play_cdbuf;
-u16 iso_play_bufptr;
-
-
-// this thread plays audio data
-#ifdef _WIN32
-static void playthread(void *param)
-#else
-static void *playthread(void *param)
-#endif
-{
- long d, t, i, s;
- unsigned char tmp;
- int sec;
-
- t = GetTickCount();
-
- iso_play_cdbuf = 0;
- iso_play_bufptr = 0;
-
- while (playing) {
- d = t - (long)GetTickCount();
- if (d <= 0) {
- d = 1;
- }
- else if (d > CDDA_FRAMETIME) {
- d = CDDA_FRAMETIME;
- }
-#ifdef _WIN32
- Sleep(d);
-#else
- usleep(d * 1000);
-#endif
-
- t = GetTickCount() + CDDA_FRAMETIME;
-
- if (subChanMixed) {
- s = 0;
-
- for (i = 0; i < sizeof(sndbuffer) / CD_FRAMESIZE_RAW; i++) {
- // read one sector
- d = fread(sndbuffer + CD_FRAMESIZE_RAW * i, 1, CD_FRAMESIZE_RAW, cddaHandle);
- if (d < CD_FRAMESIZE_RAW) {
- break;
- }
-
- s += d;
-
- fread( subbuffer, 1, SUB_FRAMESIZE, cddaHandle );
- }
- }
- else {
- s = fread(sndbuffer, 1, sizeof(sndbuffer), cddaHandle);
-
- sec = cddaCurOffset / CD_FRAMESIZE_RAW;
-
- if (subHandle != NULL) {
- fseek(subHandle, sec * SUB_FRAMESIZE, SEEK_SET);
- fread(subbuffer, 1, SUB_FRAMESIZE, subHandle);
- }
- }
-
- if (s == 0) {
- playing = FALSE;
- fclose(cddaHandle);
- cddaHandle = NULL;
- initial_offset = 0;
- break;
- }
-
- if (!cdr.Muted && playing) {
- if (cddaBigEndian) {
- for (i = 0; i < s / 2; i++) {
- tmp = sndbuffer[i * 2];
- sndbuffer[i * 2] = sndbuffer[i * 2 + 1];
- sndbuffer[i * 2 + 1] = tmp;
- }
- }
-
- // wipe data track
- if( subHandle || subChanMixed ) {
- if( ti[ ((struct SubQ *) subbuffer)->TrackNumber ].type == DATA )
- memset( sndbuffer, 0, s );
- }
-
- SPU_playCDDAchannel((short *)sndbuffer, s);
- }
-
-
- cddaCurOffset += s;
-
-
- // BIOS CD Player: Fast forward / reverse seek
- if( cdr.FastForward ) {
- // ~+0.25 sec
- cddaCurOffset += CD_FRAMESIZE_RAW * 75 * 3;
-
-#if 0
- // Bad idea: too much static
- if( subChanInterleaved )
- fseek( cddaHandle, s * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET );
- else
- fseek( cddaHandle, s * CD_FRAMESIZE_RAW, SEEK_SET );
-#endif
- }
- else if( cdr.FastBackward ) {
- // ~-0.25 sec
- cddaCurOffset -= CD_FRAMESIZE_RAW * 75 * 3;
- if( cddaCurOffset & 0x80000000 ) {
- cddaCurOffset = 0;
- cdr.FastBackward = 0;
-
- playing = 0;
- fclose(cddaHandle);
- cddaHandle = NULL;
- initial_offset = 0;
- break;
- }
-
-#if 0
- // Bad idea: too much static
- if( subChanInterleaved )
- fseek( cddaHandle, s * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET );
- else
- fseek( cddaHandle, s * CD_FRAMESIZE_RAW, SEEK_SET );
-#endif
- }
-
-
- // Vib Ribbon: decoded buffer IRQ
- iso_play_cdbuf = (u16 *)sndbuffer;
- iso_play_bufptr = 0;
- }
-
-#ifdef _WIN32
- _endthread();
-#else
- pthread_exit(0);
- return NULL;
-#endif
-}
-
-// stop the CDDA playback
-static void stopCDDA() {
- if (!playing) {
- return;
- }
-
- playing = FALSE;
-#ifdef _WIN32
- WaitForSingleObject(threadid, INFINITE);
-#else
- pthread_join(threadid, NULL);
-#endif
-
- if (cddaHandle != NULL) {
- fclose(cddaHandle);
- cddaHandle = NULL;
- }
-
- initial_offset = 0;
-}
-
-// start the CDDA playback
-static void startCDDA(unsigned int offset) {
- if (playing) {
- if (initial_offset == offset) {
- return;
- }
- stopCDDA();
- }
-
- cddaHandle = fopen(GetIsoFile(), "rb");
- if (cddaHandle == NULL) {
- return;
- }
-
- initial_offset = offset;
- cddaCurOffset = initial_offset;
- fseek(cddaHandle, initial_offset, SEEK_SET);
-
- playing = TRUE;
-
-#ifdef _WIN32
- threadid = (HANDLE)_beginthread(playthread, 0, NULL);
-#else
- pthread_create(&threadid, NULL, playthread, NULL);
-#endif
-}
-
-// this function tries to get the .toc file of the given .bin
-// the necessary data is put into the ti (trackinformation)-array
-static int parsetoc(const char *isofile) {
- char tocname[MAXPATHLEN];
- FILE *fi;
- char linebuf[256], dummy[256], name[256];
- char *token;
- char time[20], time2[20];
- unsigned int t;
-
- numtracks = 0;
-
- // copy name of the iso and change extension from .bin to .toc
- strncpy(tocname, isofile, sizeof(tocname));
- tocname[MAXPATHLEN - 1] = '\0';
- if (strlen(tocname) >= 4) {
- strcpy(tocname + strlen(tocname) - 4, ".toc");
- }
- else {
- return -1;
- }
-
- if ((fi = fopen(tocname, "r")) == NULL) {
- // try changing extension to .cue (to satisfy some stupid tutorials)
- strcpy(tocname + strlen(tocname) - 4, ".cue");
- if ((fi = fopen(tocname, "r")) == NULL) {
- // if filename is image.toc.bin, try removing .bin (for Brasero)
- strcpy(tocname, isofile);
- t = strlen(tocname);
- if (t >= 8 && strcmp(tocname + t - 8, ".toc.bin") == 0) {
- tocname[t - 4] = '\0';
- if ((fi = fopen(tocname, "r")) == NULL) {
- return -1;
- }
- }
- else {
- return -1;
- }
- }
- }
-
- memset(&ti, 0, sizeof(ti));
- cddaBigEndian = TRUE; // cdrdao uses big-endian for CD Audio
-
- // parse the .toc file
- while (fgets(linebuf, sizeof(linebuf), fi) != NULL) {
- // search for tracks
- strncpy(dummy, linebuf, sizeof(linebuf));
- token = strtok(dummy, " ");
-
- if (token == NULL) continue;
-
- if (!strcmp(token, "TRACK")) {
- // get type of track
- token = strtok(NULL, " ");
- numtracks++;
-
- if (!strncmp(token, "MODE2_RAW", 9)) {
- ti[numtracks].type = DATA;
- sec2msf(2 * 75, ti[numtracks].start); // assume data track on 0:2:0
-
- // check if this image contains mixed subchannel data
- token = strtok(NULL, " ");
- if (token != NULL && !strncmp(token, "RW_RAW", 6)) {
- subChanMixed = TRUE;
- subChanRaw = TRUE;
- }
- }
- else if (!strncmp(token, "AUDIO", 5)) {
- ti[numtracks].type = CDDA;
- }
- }
- else if (!strcmp(token, "DATAFILE")) {
- if (ti[numtracks].type == CDDA) {
- sscanf(linebuf, "DATAFILE \"%[^\"]\" #%d %8s", name, &t, time2);
- t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0);
- t += 2 * 75;
- sec2msf(t, (char *)&ti[numtracks].start);
- tok2msf((char *)&time2, (char *)&ti[numtracks].length);
- }
- else {
- sscanf(linebuf, "DATAFILE \"%[^\"]\" %8s", name, time);
- tok2msf((char *)&time, (char *)&ti[numtracks].length);
- }
- }
- else if (!strcmp(token, "FILE")) {
- sscanf(linebuf, "FILE \"%[^\"]\" #%d %8s %8s", name, &t, time, time2);
- tok2msf((char *)&time, (char *)&ti[numtracks].start);
- t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0);
- t += msf2sec(ti[numtracks].start) + 2 * 75;
- sec2msf(t, (char *)&ti[numtracks].start);
- tok2msf((char *)&time2, (char *)&ti[numtracks].length);
- }
- }
-
- fclose(fi);
-
- return 0;
-}
-
-// this function tries to get the .cue file of the given .bin
-// the necessary data is put into the ti (trackinformation)-array
-static int parsecue(const char *isofile) {
- char cuename[MAXPATHLEN];
- FILE *fi;
- char *token;
- char time[20];
- char *tmp;
- char linebuf[256], dummy[256];
- unsigned int t;
-
- numtracks = 0;
-
- // copy name of the iso and change extension from .bin to .cue
- strncpy(cuename, isofile, sizeof(cuename));
- cuename[MAXPATHLEN - 1] = '\0';
- if (strlen(cuename) >= 4) {
- strcpy(cuename + strlen(cuename) - 4, ".cue");
- }
- else {
- return -1;
- }
-
- if ((fi = fopen(cuename, "r")) == NULL) {
- return -1;
- }
-
- // Some stupid tutorials wrongly tell users to use cdrdao to rip a
- // "bin/cue" image, which is in fact a "bin/toc" image. So let's check
- // that...
- if (fgets(linebuf, sizeof(linebuf), fi) != NULL) {
- if (!strncmp(linebuf, "CD_ROM_XA", 9)) {
- // Don't proceed further, as this is actually a .toc file rather
- // than a .cue file.
- fclose(fi);
- return parsetoc(isofile);
- }
- fseek(fi, 0, SEEK_SET);
- }
-
- memset(&ti, 0, sizeof(ti));
-
- while (fgets(linebuf, sizeof(linebuf), fi) != NULL) {
- strncpy(dummy, linebuf, sizeof(linebuf));
- token = strtok(dummy, " ");
-
- if (token == NULL) {
- continue;
- }
-
- if (!strcmp(token, "TRACK")){
- numtracks++;
-
- if (strstr(linebuf, "AUDIO") != NULL) {
- ti[numtracks].type = CDDA;
- }
- else if (strstr(linebuf, "MODE1/2352") != NULL || strstr(linebuf, "MODE2/2352") != NULL) {
- ti[numtracks].type = DATA;
- }
- }
- else if (!strcmp(token, "INDEX")) {
- tmp = strstr(linebuf, "INDEX");
- if (tmp != NULL) {
- tmp += strlen("INDEX") + 3; // 3 - space + numeric index
- while (*tmp == ' ') tmp++;
- if (*tmp != '\n') sscanf(tmp, "%8s", time);
- }
-
- tok2msf((char *)&time, (char *)&ti[numtracks].start);
-
- t = msf2sec(ti[numtracks].start) + 2 * 75;
- sec2msf(t, ti[numtracks].start);
-
- // If we've already seen another track, this is its end
- if (numtracks > 1) {
- t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start);
- sec2msf(t, ti[numtracks - 1].length);
- }
- }
- }
-
- fclose(fi);
-
- // Fill out the last track's end based on size
- if (numtracks >= 1) {
- fseek(cdHandle, 0, SEEK_END);
- t = ftell(cdHandle) / 2352 - msf2sec(ti[numtracks].start) + 2 * 75;
- sec2msf(t, ti[numtracks].length);
- }
-
- return 0;
-}
-
-// this function tries to get the .ccd file of the given .img
-// the necessary data is put into the ti (trackinformation)-array
-static int parseccd(const char *isofile) {
- char ccdname[MAXPATHLEN];
- FILE *fi;
- char linebuf[256];
- unsigned int t;
-
- numtracks = 0;
-
- // copy name of the iso and change extension from .img to .ccd
- strncpy(ccdname, isofile, sizeof(ccdname));
- ccdname[MAXPATHLEN - 1] = '\0';
- if (strlen(ccdname) >= 4) {
- strcpy(ccdname + strlen(ccdname) - 4, ".ccd");
- }
- else {
- return -1;
- }
-
- if ((fi = fopen(ccdname, "r")) == NULL) {
- return -1;
- }
-
- memset(&ti, 0, sizeof(ti));
-
- while (fgets(linebuf, sizeof(linebuf), fi) != NULL) {
- if (!strncmp(linebuf, "[TRACK", 6)){
- numtracks++;
- }
- else if (!strncmp(linebuf, "MODE=", 5)) {
- sscanf(linebuf, "MODE=%d", &t);
- ti[numtracks].type = ((t == 0) ? CDDA : DATA);
- }
- else if (!strncmp(linebuf, "INDEX 1=", 8)) {
- sscanf(linebuf, "INDEX 1=%d", &t);
- sec2msf(t + 2 * 75, ti[numtracks].start);
-
- // If we've already seen another track, this is its end
- if (numtracks > 1) {
- t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start);
- sec2msf(t, ti[numtracks - 1].length);
- }
- }
- }
-
- fclose(fi);
-
- // Fill out the last track's end based on size
- if (numtracks >= 1) {
- fseek(cdHandle, 0, SEEK_END);
- t = ftell(cdHandle) / 2352 - msf2sec(ti[numtracks].start) + 2 * 75;
- sec2msf(t, ti[numtracks].length);
- }
-
- return 0;
-}
-
-// this function tries to get the .mds file of the given .mdf
-// the necessary data is put into the ti (trackinformation)-array
-static int parsemds(const char *isofile) {
- char mdsname[MAXPATHLEN];
- FILE *fi;
- unsigned int offset, extra_offset, l, i;
- unsigned short s;
-
- numtracks = 0;
-
- // copy name of the iso and change extension from .mdf to .mds
- strncpy(mdsname, isofile, sizeof(mdsname));
- mdsname[MAXPATHLEN - 1] = '\0';
- if (strlen(mdsname) >= 4) {
- strcpy(mdsname + strlen(mdsname) - 4, ".mds");
- }
- else {
- return -1;
- }
-
- if ((fi = fopen(mdsname, "rb")) == NULL) {
- return -1;
- }
-
- memset(&ti, 0, sizeof(ti));
-
- // check if it's a valid mds file
- fread(&i, 1, sizeof(unsigned int), fi);
- i = SWAP32(i);
- if (i != 0x4944454D) {
- // not an valid mds file
- fclose(fi);
- return -1;
- }
-
- // get offset to session block
- fseek(fi, 0x50, SEEK_SET);
- fread(&offset, 1, sizeof(unsigned int), fi);
- offset = SWAP32(offset);
-
- // get total number of tracks
- offset += 14;
- fseek(fi, offset, SEEK_SET);
- fread(&s, 1, sizeof(unsigned short), fi);
- s = SWAP16(s);
- numtracks = s;
-
- // get offset to track blocks
- fseek(fi, 4, SEEK_CUR);
- fread(&offset, 1, sizeof(unsigned int), fi);
- offset = SWAP32(offset);
-
- // skip lead-in data
- while (1) {
- fseek(fi, offset + 4, SEEK_SET);
- if (fgetc(fi) < 0xA0) {
- break;
- }
- offset += 0x50;
- }
-
- // check if the image contains mixed subchannel data
- fseek(fi, offset + 1, SEEK_SET);
- subChanMixed = (fgetc(fi) ? TRUE : FALSE);
-
- // read track data
- for (i = 1; i <= numtracks; i++) {
- fseek(fi, offset, SEEK_SET);
-
- // get the track type
- ti[i].type = ((fgetc(fi) == 0xA9) ? CDDA : DATA);
- fseek(fi, 8, SEEK_CUR);
-
- // get the track starting point
- ti[i].start[0] = fgetc(fi);
- ti[i].start[1] = fgetc(fi);
- ti[i].start[2] = fgetc(fi);
-
- if (i > 1) {
- l = msf2sec(ti[i].start);
- sec2msf(l - 2 * 75, ti[i].start); // ???
- }
-
- // get the track length
- fread(&extra_offset, 1, sizeof(unsigned int), fi);
- extra_offset = SWAP32(extra_offset);
-
- fseek(fi, extra_offset + 4, SEEK_SET);
- fread(&l, 1, sizeof(unsigned int), fi);
- l = SWAP32(l);
- sec2msf(l, ti[i].length);
-
- offset += 0x50;
- }
-
- fclose(fi);
- return 0;
-}
-
-// this function tries to get the .sub file of the given .img
-static int opensubfile(const char *isoname) {
- char subname[MAXPATHLEN];
-
- // copy name of the iso and change extension from .img to .sub
- strncpy(subname, isoname, sizeof(subname));
- subname[MAXPATHLEN - 1] = '\0';
- if (strlen(subname) >= 4) {
- strcpy(subname + strlen(subname) - 4, ".sub");
- }
- else {
- return -1;
- }
-
- subHandle = fopen(subname, "rb");
- if (subHandle == NULL) {
- return -1;
- }
-
- return 0;
-}
-
-long CALLBACK ISOinit(void) {
- assert(cdHandle == NULL);
- assert(subHandle == NULL);
-
- return 0; // do nothing
-}
-
-static long CALLBACK ISOshutdown(void) {
- if (cdHandle != NULL) {
- fclose(cdHandle);
- cdHandle = NULL;
- }
- if (subHandle != NULL) {
- fclose(subHandle);
- subHandle = NULL;
- }
- stopCDDA();
- return 0;
-}
-
-static void PrintTracks(void) {
- int i;
-
- for (i = 1; i <= numtracks; i++) {
- SysPrintf(_("Track %.2d (%s) - Start %.2d:%.2d:%.2d, Length %.2d:%.2d:%.2d\n"),
- i, (ti[i].type == DATA ? "DATA" : "AUDIO"),
- ti[i].start[0], ti[i].start[1], ti[i].start[2],
- ti[i].length[0], ti[i].length[1], ti[i].length[2]);
- }
-}
-
-// This function is invoked by the front-end when opening an ISO
-// file for playback
-static long CALLBACK ISOopen(void) {
- u32 modeTest = 0;
-
- if (cdHandle != NULL) {
- return 0; // it's already open
- }
-
- cdHandle = fopen(GetIsoFile(), "rb");
- if (cdHandle == NULL) {
- return -1;
- }
-
- SysPrintf(_("Loaded CD Image: %s"), GetIsoFile());
-
- cddaBigEndian = FALSE;
- subChanMixed = FALSE;
- subChanRaw = FALSE;
- isMode1ISO = FALSE;
-
- if (parseccd(GetIsoFile()) == 0) {
- SysPrintf("[+ccd]");
- }
- else if (parsemds(GetIsoFile()) == 0) {
- SysPrintf("[+mds]");
- }
- else if (parsecue(GetIsoFile()) == 0) {
- SysPrintf("[+cue]");
- }
- else if (parsetoc(GetIsoFile()) == 0) {
- SysPrintf("[+toc]");
- } else {
- //guess whether it is mode1/2048
- fseek(cdHandle, 0, SEEK_END);
- if(ftell(cdHandle) % 2048 == 0) {
- fseek(cdHandle, 0, SEEK_SET);
- fread(&modeTest, 4, 1, cdHandle);
- if(SWAP32(modeTest)!=0xffffff00) isMode1ISO = TRUE;
- }
- fseek(cdHandle, 0, SEEK_SET);
- }
-
- if (!subChanMixed && opensubfile(GetIsoFile()) == 0) {
- SysPrintf("[+sub]");
- }
-
- SysPrintf(".\n");
-
- PrintTracks();
-
- return 0;
-}
-
-static long CALLBACK ISOclose(void) {
- if (cdHandle != NULL) {
- fclose(cdHandle);
- cdHandle = NULL;
- }
- if (subHandle != NULL) {
- fclose(subHandle);
- subHandle = NULL;
- }
- stopCDDA();
- return 0;
-}
-
-// return Starting and Ending Track
-// buffer:
-// byte 0 - start track
-// byte 1 - end track
-static long CALLBACK ISOgetTN(unsigned char *buffer) {
- buffer[0] = 1;
-
- if (numtracks > 0) {
- buffer[1] = numtracks;
- }
- else {
- buffer[1] = 1;
- }
-
- return 0;
-}
-
-// return Track Time
-// buffer:
-// byte 0 - frame
-// byte 1 - second
-// byte 2 - minute
-static long CALLBACK ISOgetTD(unsigned char track, unsigned char *buffer) {
- if( track == 0 ) {
- unsigned int pos, size;
- unsigned char time[3];
-
- // Vib Ribbon: return size of CD
- // - ex. 20 min, 22 sec, 66 fra
- pos = ftell( cdHandle );
- fseek( cdHandle, 0, SEEK_END );
- size = ftell( cdHandle );
- fseek( cdHandle, pos, SEEK_SET );
-
- // relative -> absolute time (+2 seconds)
- size += 150 * 2352;
-
- sec2msf( size / 2352, time );
- buffer[2] = time[0];
- buffer[1] = time[1];
- buffer[0] = time[2];
- }
- else if (numtracks > 0 && track <= numtracks) {
- buffer[2] = ti[track].start[0];
- buffer[1] = ti[track].start[1];
- buffer[0] = ti[track].start[2];
- }
- else {
- buffer[2] = 0;
- buffer[1] = 2;
- buffer[0] = 0;
- }
-
- return 0;
-}
-
-// decode 'raw' subchannel data ripped by cdrdao
-static void DecodeRawSubData(void) {
- unsigned char subQData[12];
- int i;
-
- memset(subQData, 0, sizeof(subQData));
-
- for (i = 0; i < 8 * 12; i++) {
- if (subbuffer[i] & (1 << 6)) { // only subchannel Q is needed
- subQData[i >> 3] |= (1 << (7 - (i & 7)));
- }
- }
-
- memcpy(&subbuffer[12], subQData, 12);
-}
-
-// read track
-// time: byte 0 - minute; byte 1 - second; byte 2 - frame
-// uses bcd format
-static long CALLBACK ISOreadTrack(unsigned char *time) {
- if (cdHandle == NULL) {
- return -1;
- }
-
- if (subChanMixed) {
- fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET);
- fread(cdbuffer, 1, CD_FRAMESIZE_RAW, cdHandle);
- fread(subbuffer, 1, SUB_FRAMESIZE, cdHandle);
-
- if (subChanRaw) DecodeRawSubData();
- }
- else {
- if(isMode1ISO) {
- fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * MODE1_DATA_SIZE, SEEK_SET);
- fread(cdbuffer + 12, 1, MODE1_DATA_SIZE, cdHandle);
- memset(cdbuffer, 0, 12); //not really necessary, fake mode 2 header
- cdbuffer[0] = (time[0]);
- cdbuffer[1] = (time[1]);
- cdbuffer[2] = (time[2]);
- cdbuffer[3] = 1; //mode 1
- } else {
- fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * CD_FRAMESIZE_RAW, SEEK_SET);
- fread(cdbuffer, 1, CD_FRAMESIZE_RAW, cdHandle);
- }
-
- if (subHandle != NULL) {
- fseek(subHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * SUB_FRAMESIZE, SEEK_SET);
- fread(subbuffer, 1, SUB_FRAMESIZE, subHandle);
-
- if (subChanRaw) DecodeRawSubData();
- }
- }
-
- return 0;
-}
-
-// return readed track
-static unsigned char * CALLBACK ISOgetBuffer(void) {
- return cdbuffer+12;
-}
-
-// plays cdda audio
-// sector: byte 0 - minute; byte 1 - second; byte 2 - frame
-// does NOT uses bcd format
-static long CALLBACK ISOplay(unsigned char *time) {
- if (SPU_playCDDAchannel != NULL) {
- if (subChanMixed) {
- startCDDA(MSF2SECT(time[0], time[1], time[2]) * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE));
- }
- else {
- startCDDA(MSF2SECT(time[0], time[1], time[2]) * CD_FRAMESIZE_RAW);
- }
- }
- return 0;
-}
-
-// stops cdda audio
-static long CALLBACK ISOstop(void) {
- stopCDDA();
- return 0;
-}
-
-// gets subchannel data
-static unsigned char* CALLBACK ISOgetBufferSub(void) {
- if (subHandle != NULL || subChanMixed) {
- return subbuffer;
- }
-
- return NULL;
-}
-
-static long CALLBACK ISOgetStatus(struct CdrStat *stat) {
- u32 sect;
-
- CDR__getStatus(stat);
-
- if (playing) {
- stat->Status |= 0x80;
- }
-
- // relative -> absolute time
- sect = cddaCurOffset / CD_FRAMESIZE_RAW + 150;
- sec2msf(sect, (u8 *)stat->Time);
-
- // BIOS - boot ID (CD type)
- stat->Type = ti[1].type;
-
- return 0;
-}
-
-// read CDDA sector into buffer
-long CALLBACK ISOreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) {
- unsigned char msf[3] = {m, s, f};
- unsigned char *p;
-
- msf[0] = itob(msf[0]);
- msf[1] = itob(msf[1]);
- msf[2] = itob(msf[2]);
-
- if (ISOreadTrack(msf) != 0) return -1;
-
- p = ISOgetBuffer();
- if (p == NULL) return -1;
-
- memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector
-
- if (cddaBigEndian) {
- int i;
- unsigned char tmp;
-
- for (i = 0; i < CD_FRAMESIZE_RAW / 2; i++) {
- tmp = buffer[i * 2];
- buffer[i * 2] = buffer[i * 2 + 1];
- buffer[i * 2 + 1] = tmp;
- }
- }
-
- return 0;
-}
-
-void cdrIsoInit(void) {
- CDR_init = ISOinit;
- CDR_shutdown = ISOshutdown;
- CDR_open = ISOopen;
- CDR_close = ISOclose;
- CDR_getTN = ISOgetTN;
- CDR_getTD = ISOgetTD;
- CDR_readTrack = ISOreadTrack;
- CDR_getBuffer = ISOgetBuffer;
- CDR_play = ISOplay;
- CDR_stop = ISOstop;
- CDR_getBufferSub = ISOgetBufferSub;
- CDR_getStatus = ISOgetStatus;
- CDR_readCDDA = ISOreadCDDA;
-
- CDR_getDriveLetter = CDR__getDriveLetter;
- CDR_configure = CDR__configure;
- CDR_test = CDR__test;
- CDR_about = CDR__about;
- CDR_setfilename = CDR__setfilename;
-
- numtracks = 0;
-}
-
-int cdrIsoActive(void) {
- return (cdHandle != NULL);
-}
+/*************************************************************************** + * Copyright (C) 2007 PCSX-df Team * + * Copyright (C) 2009 Wei Mingzhi * + * * + * 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#include "psxcommon.h" +#include "plugins.h" +#include "cdrom.h" +#include "cdriso.h" + +#ifdef _WIN32 +#include <process.h> +#include <windows.h> +#else +#include <pthread.h> +#include <sys/time.h> +#include <unistd.h> +#endif + +static FILE *cdHandle = NULL; +static FILE *cddaHandle = NULL; +static FILE *subHandle = NULL; + +static boolean subChanMixed = FALSE; +static boolean subChanRaw = FALSE; + +static unsigned char cdbuffer[CD_FRAMESIZE_RAW]; +static unsigned char subbuffer[SUB_FRAMESIZE]; + +static unsigned char sndbuffer[CD_FRAMESIZE_RAW * 10]; + +#define CDDA_FRAMETIME (1000 * (sizeof(sndbuffer) / CD_FRAMESIZE_RAW) / 75) + + +#define MODE1_DATA_SIZE 2048 + +static boolean isMode1ISO = FALSE; + + +#ifdef _WIN32 +static HANDLE threadid; +#else +static pthread_t threadid; +#endif +static unsigned int initial_offset = 0; +static volatile boolean playing = FALSE; +static boolean cddaBigEndian = FALSE; +static volatile unsigned int cddaCurOffset = 0; + +char* CALLBACK CDR__getDriveLetter(void); +long CALLBACK CDR__configure(void); +long CALLBACK CDR__test(void); +void CALLBACK CDR__about(void); +long CALLBACK CDR__setfilename(char *filename); +long CALLBACK CDR__getStatus(struct CdrStat *stat); + +extern void *hCDRDriver; + +struct trackinfo { + enum {DATA=1, CDDA} type; + u8 start[3]; // MSF-format + u8 length[3]; // MSF-format +}; + +#define MAXTRACKS 100 /* How many tracks can a CD hold? */ + +static int numtracks = 0; +static struct trackinfo ti[MAXTRACKS]; + +// get a sector from a msf-array +unsigned int msf2sec(char *msf) { + return ((msf[0] * 60 + msf[1]) * 75) + msf[2]; +} + +void sec2msf(unsigned int s, char *msf) { + msf[0] = s / 75 / 60; + s = s - msf[0] * 75 * 60; + msf[1] = s / 75; + s = s - msf[1] * 75; + msf[2] = s; +} + +// divide a string of xx:yy:zz into m, s, f +static void tok2msf(char *time, char *msf) { + char *token; + + token = strtok(time, ":"); + if (token) { + msf[0] = atoi(token); + } + else { + msf[0] = 0; + } + + token = strtok(NULL, ":"); + if (token) { + msf[1] = atoi(token); + } + else { + msf[1] = 0; + } + + token = strtok(NULL, ":"); + if (token) { + msf[2] = atoi(token); + } + else { + msf[2] = 0; + } +} + +#ifndef _WIN32 +static long GetTickCount(void) { + static time_t initial_time = 0; + struct timeval now; + + gettimeofday(&now, NULL); + + if (initial_time == 0) { + initial_time = now.tv_sec; + } + + return (now.tv_sec - initial_time) * 1000L + now.tv_usec / 1000L; +} +#endif + + +u16 *iso_play_cdbuf; +u16 iso_play_bufptr; + + +// this thread plays audio data +#ifdef _WIN32 +static void playthread(void *param) +#else +static void *playthread(void *param) +#endif +{ + long d, t, i, s; + unsigned char tmp; + int sec; + + t = GetTickCount(); + + iso_play_cdbuf = 0; + iso_play_bufptr = 0; + + while (playing) { + d = t - (long)GetTickCount(); + if (d <= 0) { + d = 1; + } + else if (d > CDDA_FRAMETIME) { + d = CDDA_FRAMETIME; + } +#ifdef _WIN32 + Sleep(d); +#else + usleep(d * 1000); +#endif + + t = GetTickCount() + CDDA_FRAMETIME; + + if (subChanMixed) { + s = 0; + + for (i = 0; i < sizeof(sndbuffer) / CD_FRAMESIZE_RAW; i++) { + // read one sector + d = fread(sndbuffer + CD_FRAMESIZE_RAW * i, 1, CD_FRAMESIZE_RAW, cddaHandle); + if (d < CD_FRAMESIZE_RAW) { + break; + } + + s += d; + + fread( subbuffer, 1, SUB_FRAMESIZE, cddaHandle ); + } + } + else { + s = fread(sndbuffer, 1, sizeof(sndbuffer), cddaHandle); + + sec = cddaCurOffset / CD_FRAMESIZE_RAW; + + if (subHandle != NULL) { + fseek(subHandle, sec * SUB_FRAMESIZE, SEEK_SET); + fread(subbuffer, 1, SUB_FRAMESIZE, subHandle); + } + } + + if (s == 0) { + playing = FALSE; + fclose(cddaHandle); + cddaHandle = NULL; + initial_offset = 0; + break; + } + + if (!cdr.Muted && playing) { + if (cddaBigEndian) { + for (i = 0; i < s / 2; i++) { + tmp = sndbuffer[i * 2]; + sndbuffer[i * 2] = sndbuffer[i * 2 + 1]; + sndbuffer[i * 2 + 1] = tmp; + } + } + + // wipe data track + if( subHandle || subChanMixed ) { + if( ti[ ((struct SubQ *) subbuffer)->TrackNumber ].type == DATA ) + memset( sndbuffer, 0, s ); + } + + SPU_playCDDAchannel((short *)sndbuffer, s); + } + + + cddaCurOffset += s; + + + // BIOS CD Player: Fast forward / reverse seek + if( cdr.FastForward ) { + // ~+0.25 sec + cddaCurOffset += CD_FRAMESIZE_RAW * 75 * 3; + +#if 0 + // Bad idea: too much static + if( subChanInterleaved ) + fseek( cddaHandle, s * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET ); + else + fseek( cddaHandle, s * CD_FRAMESIZE_RAW, SEEK_SET ); +#endif + } + else if( cdr.FastBackward ) { + // ~-0.25 sec + cddaCurOffset -= CD_FRAMESIZE_RAW * 75 * 3; + if( cddaCurOffset & 0x80000000 ) { + cddaCurOffset = 0; + cdr.FastBackward = 0; + + playing = 0; + fclose(cddaHandle); + cddaHandle = NULL; + initial_offset = 0; + break; + } + +#if 0 + // Bad idea: too much static + if( subChanInterleaved ) + fseek( cddaHandle, s * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET ); + else + fseek( cddaHandle, s * CD_FRAMESIZE_RAW, SEEK_SET ); +#endif + } + + + // Vib Ribbon: decoded buffer IRQ + iso_play_cdbuf = (u16 *)sndbuffer; + iso_play_bufptr = 0; + } + +#ifdef _WIN32 + _endthread(); +#else + pthread_exit(0); + return NULL; +#endif +} + +// stop the CDDA playback +static void stopCDDA() { + if (!playing) { + return; + } + + playing = FALSE; +#ifdef _WIN32 + WaitForSingleObject(threadid, INFINITE); +#else + pthread_join(threadid, NULL); +#endif + + if (cddaHandle != NULL) { + fclose(cddaHandle); + cddaHandle = NULL; + } + + initial_offset = 0; +} + +// start the CDDA playback +static void startCDDA(unsigned int offset) { + if (playing) { + if (initial_offset == offset) { + return; + } + stopCDDA(); + } + + cddaHandle = fopen(GetIsoFile(), "rb"); + if (cddaHandle == NULL) { + return; + } + + initial_offset = offset; + cddaCurOffset = initial_offset; + fseek(cddaHandle, initial_offset, SEEK_SET); + + playing = TRUE; + +#ifdef _WIN32 + threadid = (HANDLE)_beginthread(playthread, 0, NULL); +#else + pthread_create(&threadid, NULL, playthread, NULL); +#endif +} + +// this function tries to get the .toc file of the given .bin +// the necessary data is put into the ti (trackinformation)-array +static int parsetoc(const char *isofile) { + char tocname[MAXPATHLEN]; + FILE *fi; + char linebuf[256], dummy[256], name[256]; + char *token; + char time[20], time2[20]; + unsigned int t; + + numtracks = 0; + + // copy name of the iso and change extension from .bin to .toc + strncpy(tocname, isofile, sizeof(tocname)); + tocname[MAXPATHLEN - 1] = '\0'; + if (strlen(tocname) >= 4) { + strcpy(tocname + strlen(tocname) - 4, ".toc"); + } + else { + return -1; + } + + if ((fi = fopen(tocname, "r")) == NULL) { + // try changing extension to .cue (to satisfy some stupid tutorials) + strcpy(tocname + strlen(tocname) - 4, ".cue"); + if ((fi = fopen(tocname, "r")) == NULL) { + // if filename is image.toc.bin, try removing .bin (for Brasero) + strcpy(tocname, isofile); + t = strlen(tocname); + if (t >= 8 && strcmp(tocname + t - 8, ".toc.bin") == 0) { + tocname[t - 4] = '\0'; + if ((fi = fopen(tocname, "r")) == NULL) { + return -1; + } + } + else { + return -1; + } + } + } + + memset(&ti, 0, sizeof(ti)); + cddaBigEndian = TRUE; // cdrdao uses big-endian for CD Audio + + // parse the .toc file + while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { + // search for tracks + strncpy(dummy, linebuf, sizeof(linebuf)); + token = strtok(dummy, " "); + + if (token == NULL) continue; + + if (!strcmp(token, "TRACK")) { + // get type of track + token = strtok(NULL, " "); + numtracks++; + + if (!strncmp(token, "MODE2_RAW", 9)) { + ti[numtracks].type = DATA; + sec2msf(2 * 75, ti[numtracks].start); // assume data track on 0:2:0 + + // check if this image contains mixed subchannel data + token = strtok(NULL, " "); + if (token != NULL && !strncmp(token, "RW_RAW", 6)) { + subChanMixed = TRUE; + subChanRaw = TRUE; + } + } + else if (!strncmp(token, "AUDIO", 5)) { + ti[numtracks].type = CDDA; + } + } + else if (!strcmp(token, "DATAFILE")) { + if (ti[numtracks].type == CDDA) { + sscanf(linebuf, "DATAFILE \"%[^\"]\" #%d %8s", name, &t, time2); + t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0); + t += 2 * 75; + sec2msf(t, (char *)&ti[numtracks].start); + tok2msf((char *)&time2, (char *)&ti[numtracks].length); + } + else { + sscanf(linebuf, "DATAFILE \"%[^\"]\" %8s", name, time); + tok2msf((char *)&time, (char *)&ti[numtracks].length); + } + } + else if (!strcmp(token, "FILE")) { + sscanf(linebuf, "FILE \"%[^\"]\" #%d %8s %8s", name, &t, time, time2); + tok2msf((char *)&time, (char *)&ti[numtracks].start); + t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0); + t += msf2sec(ti[numtracks].start) + 2 * 75; + sec2msf(t, (char *)&ti[numtracks].start); + tok2msf((char *)&time2, (char *)&ti[numtracks].length); + } + } + + fclose(fi); + + return 0; +} + +// this function tries to get the .cue file of the given .bin +// the necessary data is put into the ti (trackinformation)-array +static int parsecue(const char *isofile) { + char cuename[MAXPATHLEN]; + FILE *fi; + char *token; + char time[20]; + char *tmp; + char linebuf[256], dummy[256]; + unsigned int t; + + numtracks = 0; + + // copy name of the iso and change extension from .bin to .cue + strncpy(cuename, isofile, sizeof(cuename)); + cuename[MAXPATHLEN - 1] = '\0'; + if (strlen(cuename) >= 4) { + strcpy(cuename + strlen(cuename) - 4, ".cue"); + } + else { + return -1; + } + + if ((fi = fopen(cuename, "r")) == NULL) { + return -1; + } + + // Some stupid tutorials wrongly tell users to use cdrdao to rip a + // "bin/cue" image, which is in fact a "bin/toc" image. So let's check + // that... + if (fgets(linebuf, sizeof(linebuf), fi) != NULL) { + if (!strncmp(linebuf, "CD_ROM_XA", 9)) { + // Don't proceed further, as this is actually a .toc file rather + // than a .cue file. + fclose(fi); + return parsetoc(isofile); + } + fseek(fi, 0, SEEK_SET); + } + + memset(&ti, 0, sizeof(ti)); + + while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { + strncpy(dummy, linebuf, sizeof(linebuf)); + token = strtok(dummy, " "); + + if (token == NULL) { + continue; + } + + if (!strcmp(token, "TRACK")){ + numtracks++; + + if (strstr(linebuf, "AUDIO") != NULL) { + ti[numtracks].type = CDDA; + } + else if (strstr(linebuf, "MODE1/2352") != NULL || strstr(linebuf, "MODE2/2352") != NULL) { + ti[numtracks].type = DATA; + } + } + else if (!strcmp(token, "INDEX")) { + tmp = strstr(linebuf, "INDEX"); + if (tmp != NULL) { + tmp += strlen("INDEX") + 3; // 3 - space + numeric index + while (*tmp == ' ') tmp++; + if (*tmp != '\n') sscanf(tmp, "%8s", time); + } + + tok2msf((char *)&time, (char *)&ti[numtracks].start); + + t = msf2sec(ti[numtracks].start) + 2 * 75; + sec2msf(t, ti[numtracks].start); + + // If we've already seen another track, this is its end + if (numtracks > 1) { + t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start); + sec2msf(t, ti[numtracks - 1].length); + } + } + } + + fclose(fi); + + // Fill out the last track's end based on size + if (numtracks >= 1) { + fseek(cdHandle, 0, SEEK_END); + t = ftell(cdHandle) / 2352 - msf2sec(ti[numtracks].start) + 2 * 75; + sec2msf(t, ti[numtracks].length); + } + + return 0; +} + +// this function tries to get the .ccd file of the given .img +// the necessary data is put into the ti (trackinformation)-array +static int parseccd(const char *isofile) { + char ccdname[MAXPATHLEN]; + FILE *fi; + char linebuf[256]; + unsigned int t; + + numtracks = 0; + + // copy name of the iso and change extension from .img to .ccd + strncpy(ccdname, isofile, sizeof(ccdname)); + ccdname[MAXPATHLEN - 1] = '\0'; + if (strlen(ccdname) >= 4) { + strcpy(ccdname + strlen(ccdname) - 4, ".ccd"); + } + else { + return -1; + } + + if ((fi = fopen(ccdname, "r")) == NULL) { + return -1; + } + + memset(&ti, 0, sizeof(ti)); + + while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { + if (!strncmp(linebuf, "[TRACK", 6)){ + numtracks++; + } + else if (!strncmp(linebuf, "MODE=", 5)) { + sscanf(linebuf, "MODE=%d", &t); + ti[numtracks].type = ((t == 0) ? CDDA : DATA); + } + else if (!strncmp(linebuf, "INDEX 1=", 8)) { + sscanf(linebuf, "INDEX 1=%d", &t); + sec2msf(t + 2 * 75, ti[numtracks].start); + + // If we've already seen another track, this is its end + if (numtracks > 1) { + t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start); + sec2msf(t, ti[numtracks - 1].length); + } + } + } + + fclose(fi); + + // Fill out the last track's end based on size + if (numtracks >= 1) { + fseek(cdHandle, 0, SEEK_END); + t = ftell(cdHandle) / 2352 - msf2sec(ti[numtracks].start) + 2 * 75; + sec2msf(t, ti[numtracks].length); + } + + return 0; +} + +// this function tries to get the .mds file of the given .mdf +// the necessary data is put into the ti (trackinformation)-array +static int parsemds(const char *isofile) { + char mdsname[MAXPATHLEN]; + FILE *fi; + unsigned int offset, extra_offset, l, i; + unsigned short s; + + numtracks = 0; + + // copy name of the iso and change extension from .mdf to .mds + strncpy(mdsname, isofile, sizeof(mdsname)); + mdsname[MAXPATHLEN - 1] = '\0'; + if (strlen(mdsname) >= 4) { + strcpy(mdsname + strlen(mdsname) - 4, ".mds"); + } + else { + return -1; + } + + if ((fi = fopen(mdsname, "rb")) == NULL) { + return -1; + } + + memset(&ti, 0, sizeof(ti)); + + // check if it's a valid mds file + fread(&i, 1, sizeof(unsigned int), fi); + i = SWAP32(i); + if (i != 0x4944454D) { + // not an valid mds file + fclose(fi); + return -1; + } + + // get offset to session block + fseek(fi, 0x50, SEEK_SET); + fread(&offset, 1, sizeof(unsigned int), fi); + offset = SWAP32(offset); + + // get total number of tracks + offset += 14; + fseek(fi, offset, SEEK_SET); + fread(&s, 1, sizeof(unsigned short), fi); + s = SWAP16(s); + numtracks = s; + + // get offset to track blocks + fseek(fi, 4, SEEK_CUR); + fread(&offset, 1, sizeof(unsigned int), fi); + offset = SWAP32(offset); + + // skip lead-in data + while (1) { + fseek(fi, offset + 4, SEEK_SET); + if (fgetc(fi) < 0xA0) { + break; + } + offset += 0x50; + } + + // check if the image contains mixed subchannel data + fseek(fi, offset + 1, SEEK_SET); + subChanMixed = (fgetc(fi) ? TRUE : FALSE); + + // read track data + for (i = 1; i <= numtracks; i++) { + fseek(fi, offset, SEEK_SET); + + // get the track type + ti[i].type = ((fgetc(fi) == 0xA9) ? CDDA : DATA); + fseek(fi, 8, SEEK_CUR); + + // get the track starting point + ti[i].start[0] = fgetc(fi); + ti[i].start[1] = fgetc(fi); + ti[i].start[2] = fgetc(fi); + + if (i > 1) { + l = msf2sec(ti[i].start); + sec2msf(l - 2 * 75, ti[i].start); // ??? + } + + // get the track length + fread(&extra_offset, 1, sizeof(unsigned int), fi); + extra_offset = SWAP32(extra_offset); + + fseek(fi, extra_offset + 4, SEEK_SET); + fread(&l, 1, sizeof(unsigned int), fi); + l = SWAP32(l); + sec2msf(l, ti[i].length); + + offset += 0x50; + } + + fclose(fi); + return 0; +} + +// this function tries to get the .sub file of the given .img +static int opensubfile(const char *isoname) { + char subname[MAXPATHLEN]; + + // copy name of the iso and change extension from .img to .sub + strncpy(subname, isoname, sizeof(subname)); + subname[MAXPATHLEN - 1] = '\0'; + if (strlen(subname) >= 4) { + strcpy(subname + strlen(subname) - 4, ".sub"); + } + else { + return -1; + } + + subHandle = fopen(subname, "rb"); + if (subHandle == NULL) { + return -1; + } + + return 0; +} + +long CALLBACK ISOinit(void) { + assert(cdHandle == NULL); + assert(subHandle == NULL); + + return 0; // do nothing +} + +static long CALLBACK ISOshutdown(void) { + if (cdHandle != NULL) { + fclose(cdHandle); + cdHandle = NULL; + } + if (subHandle != NULL) { + fclose(subHandle); + subHandle = NULL; + } + stopCDDA(); + return 0; +} + +static void PrintTracks(void) { + int i; + + for (i = 1; i <= numtracks; i++) { + SysPrintf(_("Track %.2d (%s) - Start %.2d:%.2d:%.2d, Length %.2d:%.2d:%.2d\n"), + i, (ti[i].type == DATA ? "DATA" : "AUDIO"), + ti[i].start[0], ti[i].start[1], ti[i].start[2], + ti[i].length[0], ti[i].length[1], ti[i].length[2]); + } +} + +// This function is invoked by the front-end when opening an ISO +// file for playback +static long CALLBACK ISOopen(void) { + u32 modeTest = 0; + + if (cdHandle != NULL) { + return 0; // it's already open + } + + cdHandle = fopen(GetIsoFile(), "rb"); + if (cdHandle == NULL) { + return -1; + } + + SysPrintf(_("Loaded CD Image: %s"), GetIsoFile()); + + cddaBigEndian = FALSE; + subChanMixed = FALSE; + subChanRaw = FALSE; + isMode1ISO = FALSE; + + if (parseccd(GetIsoFile()) == 0) { + SysPrintf("[+ccd]"); + } + else if (parsemds(GetIsoFile()) == 0) { + SysPrintf("[+mds]"); + } + else if (parsecue(GetIsoFile()) == 0) { + SysPrintf("[+cue]"); + } + else if (parsetoc(GetIsoFile()) == 0) { + SysPrintf("[+toc]"); + } else { + //guess whether it is mode1/2048 + fseek(cdHandle, 0, SEEK_END); + if(ftell(cdHandle) % 2048 == 0) { + fseek(cdHandle, 0, SEEK_SET); + fread(&modeTest, 4, 1, cdHandle); + if(SWAP32(modeTest)!=0xffffff00) isMode1ISO = TRUE; + } + fseek(cdHandle, 0, SEEK_SET); + } + + if (!subChanMixed && opensubfile(GetIsoFile()) == 0) { + SysPrintf("[+sub]"); + } + + SysPrintf(".\n"); + + PrintTracks(); + + return 0; +} + +static long CALLBACK ISOclose(void) { + if (cdHandle != NULL) { + fclose(cdHandle); + cdHandle = NULL; + } + if (subHandle != NULL) { + fclose(subHandle); + subHandle = NULL; + } + stopCDDA(); + return 0; +} + +// return Starting and Ending Track +// buffer: +// byte 0 - start track +// byte 1 - end track +static long CALLBACK ISOgetTN(unsigned char *buffer) { + buffer[0] = 1; + + if (numtracks > 0) { + buffer[1] = numtracks; + } + else { + buffer[1] = 1; + } + + return 0; +} + +// return Track Time +// buffer: +// byte 0 - frame +// byte 1 - second +// byte 2 - minute +static long CALLBACK ISOgetTD(unsigned char track, unsigned char *buffer) { + if( track == 0 ) { + unsigned int pos, size; + unsigned char time[3]; + + // Vib Ribbon: return size of CD + // - ex. 20 min, 22 sec, 66 fra + pos = ftell( cdHandle ); + fseek( cdHandle, 0, SEEK_END ); + size = ftell( cdHandle ); + fseek( cdHandle, pos, SEEK_SET ); + + // relative -> absolute time (+2 seconds) + size += 150 * 2352; + + sec2msf( size / 2352, time ); + buffer[2] = time[0]; + buffer[1] = time[1]; + buffer[0] = time[2]; + } + else if (numtracks > 0 && track <= numtracks) { + buffer[2] = ti[track].start[0]; + buffer[1] = ti[track].start[1]; + buffer[0] = ti[track].start[2]; + } + else { + buffer[2] = 0; + buffer[1] = 2; + buffer[0] = 0; + } + + return 0; +} + +// decode 'raw' subchannel data ripped by cdrdao +static void DecodeRawSubData(void) { + unsigned char subQData[12]; + int i; + + memset(subQData, 0, sizeof(subQData)); + + for (i = 0; i < 8 * 12; i++) { + if (subbuffer[i] & (1 << 6)) { // only subchannel Q is needed + subQData[i >> 3] |= (1 << (7 - (i & 7))); + } + } + + memcpy(&subbuffer[12], subQData, 12); +} + +// read track +// time: byte 0 - minute; byte 1 - second; byte 2 - frame +// uses bcd format +static long CALLBACK ISOreadTrack(unsigned char *time) { + if (cdHandle == NULL) { + return -1; + } + + if (subChanMixed) { + fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET); + fread(cdbuffer, 1, CD_FRAMESIZE_RAW, cdHandle); + fread(subbuffer, 1, SUB_FRAMESIZE, cdHandle); + + if (subChanRaw) DecodeRawSubData(); + } + else { + if(isMode1ISO) { + fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * MODE1_DATA_SIZE, SEEK_SET); + fread(cdbuffer + 12, 1, MODE1_DATA_SIZE, cdHandle); + memset(cdbuffer, 0, 12); //not really necessary, fake mode 2 header + cdbuffer[0] = (time[0]); + cdbuffer[1] = (time[1]); + cdbuffer[2] = (time[2]); + cdbuffer[3] = 1; //mode 1 + } else { + fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * CD_FRAMESIZE_RAW, SEEK_SET); + fread(cdbuffer, 1, CD_FRAMESIZE_RAW, cdHandle); + } + + if (subHandle != NULL) { + fseek(subHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * SUB_FRAMESIZE, SEEK_SET); + fread(subbuffer, 1, SUB_FRAMESIZE, subHandle); + + if (subChanRaw) DecodeRawSubData(); + } + } + + return 0; +} + +// return readed track +static unsigned char * CALLBACK ISOgetBuffer(void) { + return cdbuffer+12; +} + +// plays cdda audio +// sector: byte 0 - minute; byte 1 - second; byte 2 - frame +// does NOT uses bcd format +static long CALLBACK ISOplay(unsigned char *time) { + if (SPU_playCDDAchannel != NULL) { + if (subChanMixed) { + startCDDA(MSF2SECT(time[0], time[1], time[2]) * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE)); + } + else { + startCDDA(MSF2SECT(time[0], time[1], time[2]) * CD_FRAMESIZE_RAW); + } + } + return 0; +} + +// stops cdda audio +static long CALLBACK ISOstop(void) { + stopCDDA(); + return 0; +} + +// gets subchannel data +static unsigned char* CALLBACK ISOgetBufferSub(void) { + if (subHandle != NULL || subChanMixed) { + return subbuffer; + } + + return NULL; +} + +static long CALLBACK ISOgetStatus(struct CdrStat *stat) { + u32 sect; + + CDR__getStatus(stat); + + if (playing) { + stat->Status |= 0x80; + } + + // relative -> absolute time + sect = cddaCurOffset / CD_FRAMESIZE_RAW + 150; + sec2msf(sect, (u8 *)stat->Time); + + // BIOS - boot ID (CD type) + stat->Type = ti[1].type; + + return 0; +} + +// read CDDA sector into buffer +long CALLBACK ISOreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) { + unsigned char msf[3] = {m, s, f}; + unsigned char *p; + + msf[0] = itob(msf[0]); + msf[1] = itob(msf[1]); + msf[2] = itob(msf[2]); + + if (ISOreadTrack(msf) != 0) return -1; + + p = ISOgetBuffer(); + if (p == NULL) return -1; + + memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector + + if (cddaBigEndian) { + int i; + unsigned char tmp; + + for (i = 0; i < CD_FRAMESIZE_RAW / 2; i++) { + tmp = buffer[i * 2]; + buffer[i * 2] = buffer[i * 2 + 1]; + buffer[i * 2 + 1] = tmp; + } + } + + return 0; +} + +void cdrIsoInit(void) { + CDR_init = ISOinit; + CDR_shutdown = ISOshutdown; + CDR_open = ISOopen; + CDR_close = ISOclose; + CDR_getTN = ISOgetTN; + CDR_getTD = ISOgetTD; + CDR_readTrack = ISOreadTrack; + CDR_getBuffer = ISOgetBuffer; + CDR_play = ISOplay; + CDR_stop = ISOstop; + CDR_getBufferSub = ISOgetBufferSub; + CDR_getStatus = ISOgetStatus; + CDR_readCDDA = ISOreadCDDA; + + CDR_getDriveLetter = CDR__getDriveLetter; + CDR_configure = CDR__configure; + CDR_test = CDR__test; + CDR_about = CDR__about; + CDR_setfilename = CDR__setfilename; + + numtracks = 0; +} + +int cdrIsoActive(void) { + return (cdHandle != NULL); +} diff --git a/libpcsxcore/cdriso.h b/libpcsxcore/cdriso.h index 8c35445d..9c6359e6 100644..100755 --- a/libpcsxcore/cdriso.h +++ b/libpcsxcore/cdriso.h @@ -1,34 +1,34 @@ -/***************************************************************************
- * Copyright (C) 2007 PCSX-df Team *
- * Copyright (C) 2009 Wei Mingzhi *
- * *
- * 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#ifndef CDRISO_H
-#define CDRISO_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void cdrIsoInit(void);
-int cdrIsoActive(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 PCSX-df Team * + * Copyright (C) 2009 Wei Mingzhi * + * * + * 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef CDRISO_H +#define CDRISO_H + +#ifdef __cplusplus +extern "C" { +#endif + +void cdrIsoInit(void); +int cdrIsoActive(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 405f2a88..b9e9d1ba 100644..100755 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -1,2507 +1,2507 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* Handles all CD-ROM registers and functions.
-*/
-
-#include "cdrom.h"
-#include "ppf.h"
-#include "psxdma.h"
-
-cdrStruct cdr;
-
-/* CD-ROM magic numbers */
-#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 CdlReadT 18
-#define CdlGetTN 19
-#define CdlGetTD 20
-#define CdlSeekL 21
-#define CdlSeekP 22
-#define CdlSetclock 23
-#define CdlGetclock 24
-#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", "CdlReadT", "CdlGetTN",
- "CdlGetTD", "CdlSeekL", "CdlSeekP", "CdlSetclock",
- "CdlGetclock", "CdlTest", "CdlID", "CdlReadS",
- "CdlReset", NULL, "CDlReadToc", NULL
-};
-
-unsigned char Test04[] = { 0 };
-unsigned char Test05[] = { 0 };
-unsigned char Test20[] = { 0x98, 0x06, 0x10, 0xC3 };
-unsigned char Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F };
-unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 };
-
-// cdr.Stat:
-#define NoIntr 0
-#define DataReady 1
-#define Complete 2
-#define Acknowledge 3
-#define DataEnd 4
-#define DiskError 5
-
-/* Modes flags */
-#define MODE_SPEED (1<<7) // 0x80
-#define MODE_STRSND (1<<6) // 0x40 ADPCM on/off
-#define MODE_SIZE_2340 (1<<5) // 0x20
-#define MODE_SIZE_2328 (1<<4) // 0x10
-#define MODE_SIZE_2048 (0<<4) // 0x00
-#define MODE_SF (1<<3) // 0x08 channel on/off
-#define MODE_REPORT (1<<2) // 0x04
-#define MODE_AUTOPAUSE (1<<1) // 0x02
-#define MODE_CDDA (1<<0) // 0x01
-
-/* Status flags */
-#define STATUS_PLAY (1<<7) // 0x80
-#define STATUS_SEEK (1<<6) // 0x40
-#define STATUS_READ (1<<5) // 0x20
-#define STATUS_SHELLOPEN (1<<4) // 0x10
-#define STATUS_UNKNOWN3 (1<<3) // 0x08
-#define STATUS_UNKNOWN2 (1<<2) // 0x04
-#define STATUS_ROTATING (1<<1) // 0x02
-#define STATUS_ERROR (1<<0) // 0x01
-
-#define XA_ATTENUATE 0
-#define CDDA_ATTENUATE 1
-
-// 1x = 75 sectors per second
-// PSXCLK = 1 sec in the ps
-// so (PSXCLK / 75) = cdr read time (linuzappz)
-#define cdReadTime (PSXCLK / 75)
-
-static struct CdrStat stat;
-static struct SubQ *subq;
-
-
-extern unsigned int msf2sec(char *msf);
-extern void sec2msf(unsigned int s, char *msf);
-
-
-extern u16 *iso_play_cdbuf;
-extern u16 iso_play_bufptr;
-extern long CALLBACK ISOinit(void);
-extern void CALLBACK SPUirq(void);
-extern SPUregisterCallback SPU_registerCallback;
-
-// A bit of a kludge, but it will get rid of the "macro redefined" warnings
-
-#ifdef H_SPUirqAddr
-#undef H_SPUirqAddr
-#endif
-
-#ifdef H_SPUaddr
-#undef H_SPUaddr
-#endif
-
-#ifdef H_SPUctrl
-#undef H_SPUctrl
-#endif
-
-#define H_SPUirqAddr 0x1f801da4
-#define H_SPUaddr 0x1f801da6
-#define H_SPUctrl 0x1f801daa
-#define H_CDLeft 0x1f801db0
-#define H_CDRight 0x1f801db2
-
-
-#define CDR_INT(eCycle) { \
- psxRegs.interrupt |= (1 << PSXINT_CDR); \
- psxRegs.intCycle[PSXINT_CDR].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_CDR].sCycle = psxRegs.cycle; \
-}
-
-#define CDREAD_INT(eCycle) { \
- psxRegs.interrupt |= (1 << PSXINT_CDREAD); \
- psxRegs.intCycle[PSXINT_CDREAD].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_CDREAD].sCycle = psxRegs.cycle; \
-}
-
-#define CDRDBUF_INT(eCycle) { \
- psxRegs.interrupt |= (1 << PSXINT_CDRDBUF); \
- psxRegs.intCycle[PSXINT_CDRDBUF].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_CDRDBUF].sCycle = psxRegs.cycle; \
-}
-
-#define CDRLID_INT(eCycle) { \
- psxRegs.interrupt |= (1 << PSXINT_CDRLID); \
- psxRegs.intCycle[PSXINT_CDRLID].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_CDRLID].sCycle = psxRegs.cycle; \
-}
-
-#define CDRPLAY_INT(eCycle) { \
- psxRegs.interrupt |= (1 << PSXINT_CDRPLAY); \
- psxRegs.intCycle[PSXINT_CDRPLAY].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_CDRPLAY].sCycle = psxRegs.cycle; \
-}
-
-#define StartReading(type, eCycle) { \
- cdr.Reading = type; \
- cdr.FirstSector = 1; \
- cdr.Readed = 0xff; \
- AddIrqQueue(READ_ACK, eCycle); \
-}
-
-#define StopReading() { \
- if (cdr.Reading) { \
- cdr.Reading = 0; \
- psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); \
- } \
- cdr.StatP &= ~STATUS_READ;\
-}
-
-#define StopCdda() { \
- if (cdr.Play) { \
- if (!Config.Cdda) CDR_stop(); \
- cdr.StatP &= ~STATUS_PLAY; \
- cdr.Play = FALSE; \
- cdr.FastForward = 0; \
- cdr.FastBackward = 0; \
- SPU_registerCallback( SPUirq ); \
- } \
-}
-
-#define SetResultSize(size) { \
- cdr.ResultP = 0; \
- cdr.ResultC = size; \
- cdr.ResultReady = 1; \
-}
-
-void adjustTransferIndex()
-{
- unsigned int bufSize = 0;
-
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- //Do we need a default case in this switch?
- case MODE_SIZE_2340: bufSize = 2340; break;
- case MODE_SIZE_2328: bufSize = 12 + 2328; break;
- case MODE_SIZE_2048: bufSize = 12 + 2048; break;
- }
-
- if (cdr.transferIndex >= bufSize)
- {
- if (bufSize == 0) {
- //Make sure we don't divide by zero
- //Do nothing
- } else {
- cdr.transferIndex %= bufSize;
- }
- }
-}
-
-void cdrDecodedBufferInterrupt()
-{
- u16 buf_ptr[0x400], lcv;
-
-#if 0
- return;
-#endif
-
-
- // ISO reader only
- if( CDR_init != ISOinit ) return;
-
-
- // check dbuf IRQ still active
- if( cdr.Play == 0 ) return;
- if( (SPU_readRegister( H_SPUctrl ) & 0x40) == 0 ) return;
- if( (SPU_readRegister( H_SPUirqAddr ) * 8) >= 0x800 ) return;
-
-
-
- // turn off plugin SPU IRQ decoded buffer handling
- SPU_registerCallback( 0 );
-
-
-
- /*
- Vib Ribbon
-
- 000-3FF = left CDDA
- 400-7FF = right CDDA
-
- Assume IRQ every wrap
- */
-
- if( iso_play_cdbuf )
- {
- for( lcv = 0; lcv < 0x200; lcv++ )
- {
- // left
- buf_ptr[ lcv ] = iso_play_cdbuf[ iso_play_bufptr ];
-
- // right
- buf_ptr[ lcv+0x200 ] = iso_play_cdbuf[ iso_play_bufptr+1 ];
-
- iso_play_bufptr += 2;
- }
- }
- else
- {
- memset( buf_ptr, 0, sizeof(buf_ptr) );
- }
-
-
- // feed CDDA decoded buffer manually
- SPU_writeRegister( H_SPUaddr,0 );
- SPU_writeDMAMem( buf_ptr, 0x800 / 2 );
-
-
- // signal CDDA data ready
- psxHu32ref(0x1070) |= SWAP32((u32)0x200);
-
-
- // time for next full buffer
- //CDRDBUF_INT( PSXCLK / 44100 * 0x200 );
- CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
-}
-
-
-void cdrLidSeekInterrupt()
-{
- // turn back on checking
- if( cdr.LidCheck == 0x10 )
- {
- cdr.LidCheck = 0;
- }
-
- // official lid close
- else if( cdr.LidCheck == 0x30 )
- {
- // GS CDX 3.3: $13
- cdr.StatP |= STATUS_ROTATING;
-
-
- // GS CDX 3.3 - ~50 getlocp tries
- CDRLID_INT( cdReadTime * 3 );
- cdr.LidCheck = 0x40;
- }
-
- // turn off ready
- else if( cdr.LidCheck == 0x40 )
- {
- // GS CDX 3.3: $01
- cdr.StatP &= ~STATUS_SHELLOPEN;
- cdr.StatP &= ~STATUS_ROTATING;
-
-
- // GS CDX 3.3 - ~50 getlocp tries
- CDRLID_INT( cdReadTime * 3 );
- cdr.LidCheck = 0x50;
- }
-
- // now seek
- else if( cdr.LidCheck == 0x50 )
- {
- // GameShark Lite: Start seeking ($42)
- cdr.StatP |= STATUS_SEEK;
- cdr.StatP |= STATUS_ROTATING;
- cdr.StatP &= ~STATUS_ERROR;
-
-
- CDRLID_INT( cdReadTime * 3 );
- cdr.LidCheck = 0x60;
- }
-
- // done = cd ready
- else if( cdr.LidCheck == 0x60 )
- {
- // GameShark Lite: Seek detection done ($02)
- cdr.StatP &= ~STATUS_SEEK;
-
- cdr.LidCheck = 0;
- }
-}
-
-
-void Check_Shell( int Irq )
-{
- // check case open/close
- if (cdr.LidCheck > 0)
- {
-#ifdef CDR_LOG
- CDR_LOG( "LidCheck\n" );
-#endif
-
- // $20 = check lid state
- if( cdr.LidCheck == 0x20 )
- {
- u32 i;
-
- i = stat.Status;
- if (CDR_getStatus(&stat) != -1)
- {
- // BIOS hangs + BIOS error messages
- //if (stat.Type == 0xff)
- //cdr.Stat = DiskError;
-
- // case now open
- if (stat.Status & STATUS_SHELLOPEN)
- {
- // Vib Ribbon: pre-CD swap
- StopCdda();
-
-
- // GameShark Lite: Death if DiskError happens
- //
- // Vib Ribbon: Needs DiskError for CD swap
-
- if (Irq != CdlNop)
- {
- cdr.Stat = DiskError;
-
- cdr.StatP |= STATUS_ERROR;
- cdr.Result[0] |= STATUS_ERROR;
- }
-
- // GameShark Lite: Wants -exactly- $10
- cdr.StatP |= STATUS_SHELLOPEN;
- cdr.StatP &= ~STATUS_ROTATING;
-
-
- CDRLID_INT( cdReadTime * 3 );
- cdr.LidCheck = 0x10;
-
-
- // GS CDX 3.3 = $11
- }
-
- // case just closed
- else if ( i & STATUS_SHELLOPEN )
- {
- cdr.StatP |= STATUS_ROTATING;
-
- CheckCdrom();
-
-
- if( cdr.Stat == NoIntr )
- cdr.Stat = Acknowledge;
-
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
-
- // begin close-seek-ready cycle
- CDRLID_INT( cdReadTime * 3 );
- cdr.LidCheck = 0x30;
-
-
- // GameShark Lite: Wants -exactly- $42, then $02
- // GS CDX 3.3: Wants $11/$80, $13/$80, $01/$00
- }
-
- // case still closed - wait for recheck
- else
- {
- CDRLID_INT( cdReadTime * 3 );
- cdr.LidCheck = 0x10;
- }
- }
- }
-
-
- // GS CDX: clear all values but #1,#2
- if( (cdr.LidCheck >= 0x30) || (cdr.StatP & STATUS_SHELLOPEN) )
- {
- SetResultSize(16);
- memset( cdr.Result, 0, 16 );
-
- cdr.Result[0] = cdr.StatP;
-
-
- // GS CDX: special return value
- if( cdr.StatP & STATUS_SHELLOPEN )
- {
- cdr.Result[1] = 0x80;
- }
-
-
- if( cdr.Stat == NoIntr )
- cdr.Stat = Acknowledge;
-
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
- }
-}
-
-
-void Find_CurTrack() {
- cdr.CurTrack = 0;
-
- if (CDR_getTN(cdr.ResultTN) != -1) {
- int lcv;
-
- for( lcv = 1; lcv <= cdr.ResultTN[1]; lcv++ ) {
- if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) {
- u32 sect1, sect2;
-
-#ifdef CDR_LOG___0
- CDR_LOG( "curtrack %d %d %d | %d %d %d | %d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2],
- cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0],
- cdr.CurTrack );
-#endif
-
- // find next track boundary - only need m:s accuracy
- sect1 = cdr.SetSectorPlay[0] * 60 * 75 + cdr.SetSectorPlay[1] * 75;
- sect2 = cdr.ResultTD[2] * 60 * 75 + cdr.ResultTD[1] * 75;
-
- // Twisted Metal 4 - psx cdda pregap (2-sec)
- // - fix in-game music
- sect2 -= 75 * 2;
-
- if( sect1 >= sect2 ) {
- cdr.CurTrack++;
- continue;
- }
- }
-
- break;
- }
- }
-}
-
-static void ReadTrack( u8 *time ) {
- cdr.Prev[0] = itob( time[0] );
- cdr.Prev[1] = itob( time[1] );
- cdr.Prev[2] = itob( time[2] );
-
-#ifdef CDR_LOG
- CDR_LOG("ReadTrack() Log: KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
-#endif
- cdr.RErr = CDR_readTrack(cdr.Prev);
-}
-
-
-static void CDXA_Attenuation( s16 *buf, int size, int stereo, int attenuate_type )
-{
- s16 *spsound;
- s32 lc = 0, rc = 0;
- int i;
-
- spsound = buf;
-
-#if 0
- // mono xa attenuation
- // - Tales of Phantasia (voice meter)
- if( stereo == 0 ) {
- s16 temp[32768];
- int dst;
-
- dst = 0;
- for( i = 0; i < size; i++, dst+=2 ) {
- temp[dst+0] = spsound[i];
- temp[dst+1] = spsound[i];
- }
-
- size *= 2*2;
- memcpy( spsound, temp, size );
- }
-#endif
-
- for( i = 0; i < size / 2; i += 2 )
- {
- // Chronicles of the Sword - cutscene (xa), speech (cdda)
- if( attenuate_type == XA_ATTENUATE ) {
- lc = (spsound[i+0] * cdr.AttenuatorLeft[0] + spsound[i+1] * cdr.AttenuatorLeft[1]) / 128;
- rc = (spsound[i+1] * cdr.AttenuatorRight[0] + spsound[i+0] * cdr.AttenuatorRight[1]) / 128;
- } else if( attenuate_type == CDDA_ATTENUATE ) {
- lc = (spsound[i+0] * cdr.AttenuatorLeft[0] + spsound[i+1] * cdr.AttenuatorRight[1]) / 128;
- rc = (spsound[i+1] * cdr.AttenuatorRight[0] + spsound[i+0] * cdr.AttenuatorLeft[1]) / 128;
- }
-
- if( lc < -32768 ) lc = -32768;
- if( rc < -32768 ) rc = -32768;
- if( lc > 32767 ) lc = 32767;
- if( rc > 32767 ) rc = 32767;
-
- spsound[i + 0] = lc;
- spsound[i + 1] = rc;
- }
-}
-
-
-void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
- cdr.Irq = irq;
- cdr.eCycle = ecycle;
-
- // Doom: Force rescheduling
- // - Fixes boot
- CDR_INT(ecycle);
-}
-
-
-void Set_Track()
-{
- if (CDR_getTN(cdr.ResultTN) != -1) {
- int lcv;
-
- for( lcv = 1; lcv < cdr.ResultTN[1]; lcv++ ) {
- if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) {
-#ifdef CDR_LOG___0
- CDR_LOG( "settrack %d %d %d | %d %d %d | %d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2],
- cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0],
- cdr.CurTrack );
-#endif
-
- // check if time matches track start (only need min, sec accuracy)
- // - m:s:f vs f:s:m
- if( cdr.SetSectorPlay[0] == cdr.ResultTD[2] &&
- cdr.SetSectorPlay[1] == cdr.ResultTD[1] ) {
- // skip pregap frames
- if( cdr.SetSectorPlay[2] < cdr.ResultTD[0] )
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
-
- break;
- }
- else if( cdr.SetSectorPlay[0] < cdr.ResultTD[2] )
- break;
- }
- }
- }
-}
-
-
-static u8 fake_subq_local[3], fake_subq_real[3], fake_subq_index, fake_subq_change;
-void Create_Fake_Subq()
-{
- u8 temp_cur[3], temp_next[3], temp_start[3], pregap;
- int diff;
-
- if (CDR_getTN(cdr.ResultTN) == -1) return;
- if( cdr.CurTrack+1 <= cdr.ResultTN[1] ) {
- pregap = 150;
- if( CDR_getTD(cdr.CurTrack+1, cdr.ResultTD) == -1 ) return;
- } else {
- // last track - cd size
- pregap = 0;
- if( CDR_getTD(0, cdr.ResultTD) == -1 ) return;
- }
-
- if( cdr.Play == TRUE ) {
- temp_cur[0] = cdr.SetSectorPlay[0];
- temp_cur[1] = cdr.SetSectorPlay[1];
- temp_cur[2] = cdr.SetSectorPlay[2];
- } else {
- temp_cur[0] = btoi( cdr.Prev[0] );
- temp_cur[1] = btoi( cdr.Prev[1] );
- temp_cur[2] = btoi( cdr.Prev[2] );
- }
-
- fake_subq_real[0] = temp_cur[0];
- fake_subq_real[1] = temp_cur[1];
- fake_subq_real[2] = temp_cur[2];
-
- temp_next[0] = cdr.ResultTD[2];
- temp_next[1] = cdr.ResultTD[1];
- temp_next[2] = cdr.ResultTD[0];
-
-
- // flag- next track
- if( msf2sec(temp_cur) >= msf2sec( temp_next )-pregap ) {
- fake_subq_change = 1;
-
- cdr.CurTrack++;
-
- // end cd
- if( pregap == 0 ) StopCdda();
- }
-
- //////////////////////////////////////////////////
- //////////////////////////////////////////////////
-
- // repair
- if( cdr.CurTrack <= cdr.ResultTN[1] ) {
- if( CDR_getTD(cdr.CurTrack, cdr.ResultTD) == -1 ) return;
- } else {
- // last track - cd size
- if( CDR_getTD(0, cdr.ResultTD) == -1 ) return;
- }
-
- temp_start[0] = cdr.ResultTD[2];
- temp_start[1] = cdr.ResultTD[1];
- temp_start[2] = cdr.ResultTD[0];
-
-
-#ifdef CDR_LOG
- CDR_LOG( "CDDA FAKE SUB - %d:%d:%d / %d:%d:%d / %d:%d:%d\n",
- temp_cur[0], temp_cur[1], temp_cur[2],
- temp_start[0], temp_start[1], temp_start[2],
- temp_next[0], temp_next[1], temp_next[2]);
-#endif
-
-
-
- // local time - pregap / real
- diff = msf2sec(temp_cur) - msf2sec( temp_start );
- if( diff < 0 ) {
- fake_subq_index = 0;
-
- sec2msf( -diff, fake_subq_local );
- } else {
- fake_subq_index = 1;
-
- sec2msf( diff, fake_subq_local );
- }
-}
-
-
-void cdrPlayInterrupt_Autopause()
-{
- if ((cdr.Mode & (MODE_AUTOPAUSE|MODE_CDDA)) != (MODE_AUTOPAUSE|MODE_CDDA)) return;
-
- // Reschedule IRQ
- if ( cdr.Irq || cdr.Stat ) {
-#ifdef CDR_LOG
- CDR_LOG("=== BUSY === cdrPlayInterrupt\n");
-#endif
-
- //CDRPLAY_INT( 0x800 );
- return;
- }
-
-
- if( CDR_getStatus(&stat) == -1) return;
-
- subq = (struct SubQ *)CDR_getBufferSub();
-
- if (subq != NULL ) {
-#ifdef CDR_LOG
- CDR_LOG( "CDDA SUB - %X:%X:%X\n",
- subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
-#endif
-
- /*
- CDDA Autopause
-
- Silhouette Mirage ($3)
- Tomb Raider 1 ($7)
- */
-
- if( cdr.CurTrack < btoi( subq->TrackNumber ) ) {
-#ifdef CDR_LOG
- CDR_LOG( "CDDA STOP\n" );
-#endif
-
- // Magic the Gathering
- // - looping territory cdda
-
- // ...?
- //cdr.ResultReady = 1;
- //cdr.Stat = DataReady;
- cdr.Stat = DataEnd;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
-
- StopCdda();
- }
- } else {
-#ifdef CDR_LOG___0
- CDR_LOG( "CDDA FAKE SUB - %d:%d:%d\n",
- temp_cur[0], temp_cur[1], temp_cur[2] );
-#endif
-
- //if( msf2sec(temp_cur) >= msf2sec( temp_next ) ) {
- if( fake_subq_change ) {
-#ifdef CDR_LOG
- CDR_LOG( "CDDA STOP\n" );
-#endif
-
- // Magic the Gathering
- // - looping territory cdda
-
- // ...?
- //cdr.ResultReady = 1;
- //cdr.Stat = DataReady;
- cdr.Stat = DataEnd;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
-
- StopCdda();
-
- fake_subq_change = 0;
- }
- }
-}
-
-
-void cdrPlayInterrupt_Repplay()
-{
- // BIOS - HACK: Switch between local / absolute times
- static u8 report_time = 1;
-
-
- if ((cdr.Mode & (MODE_REPORT|MODE_CDDA)) != (MODE_REPORT|MODE_CDDA)) return;
-
-#ifdef CDR_LOG
- CDR_LOG("cdrRepplayInterrupt() Log: KEY END\n");
-#endif
-
- // Doom - no more cdda playing
- // - fixes boot with irq cmd reschedule
-
- // Reschedule IRQ
- if ( cdr.Irq || cdr.Stat ) {
-#ifdef CDR_LOG
- CDR_LOG("=== BUSY === cdrRepplayInterrupt\n");
-#endif
-
- //CDREPPLAY_INT( 0x800 );
- return;
- }
-
-
- memset( cdr.Result, 0, 8 );
- if( CDR_getStatus(&stat) == -1) return;
-
- cdr.Result[0] = cdr.StatP;
-
-
- subq = (struct SubQ *)CDR_getBufferSub();
- if (subq != NULL ) {
-#ifdef CDR_LOG
- CDR_LOG( "REPPLAY SUB - %X:%X:%X\n",
- subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
-#endif
-
-
- /*
- skip subQ integrity check (audio playback)
- - mainly useful for DATA LibCrypt checking
- */
- //if( SWAP16(subq->CRC) != calcCrc((unsigned char *)subq + 12, 10) )
-
- // Rayman: audio pregap flag / track change
- // - not all CDs will use PREGAPs, so we track it manually
- if( cdr.CurTrack < btoi( subq->TrackNumber ) ) {
- cdr.Result[0] |= 0x10;
-
- cdr.CurTrack = btoi( subq->TrackNumber );
- }
-
-
- // BIOS CD Player: data already BCD format
- cdr.Result[1] = subq->TrackNumber;
- cdr.Result[2] = subq->IndexNumber;
-
-
- // BIOS CD Player: switch between local / absolute times
- if( report_time == 0 ) {
- cdr.Result[3] = subq->AbsoluteAddress[0];
- cdr.Result[4] = subq->AbsoluteAddress[1];
- cdr.Result[5] = subq->AbsoluteAddress[2];
-
- report_time = 1;
- } else {
- cdr.Result[3] = subq->TrackRelativeAddress[0];
- cdr.Result[4] = subq->TrackRelativeAddress[1];
- cdr.Result[5] = subq->TrackRelativeAddress[2];
-
- cdr.Result[4] |= 0x80;
-
- report_time = 0;
- }
- } else {
-#ifdef CDR_LOG___0
- CDR_LOG( "REPPLAY FAKE - %d:%d:%d\n",
- temp_cur[0], temp_cur[1], temp_cur[2] );
-#endif
-
- // Rayman: check track change
- //if( msf2sec(temp_cur) >= msf2sec( temp_next ) ) {
- if( fake_subq_change ) {
-#ifdef CDR_LOG___0
- CDR_LOG( "TRACK CHANGE %d - %d %d %d ==> %d %d %d\n",
- cdr.CurTrack,
- temp_cur[0], temp_cur[1], temp_cur[2],
- temp_next[0], temp_next[1], temp_next[2] );
-#endif
-
- cdr.Result[0] |= 0x10;
-
- fake_subq_change = 0;
- }
-
-
- // track # / index #
- cdr.Result[1] = itob(cdr.CurTrack);
- cdr.Result[2] = itob(fake_subq_index);
-
- if( report_time == 0 ) {
- // absolute
- cdr.Result[3] = itob( fake_subq_real[0] );
- cdr.Result[4] = itob( fake_subq_real[1] );
- cdr.Result[5] = itob( fake_subq_real[2] );
-
- report_time = 1;
- } else {
- // local
- cdr.Result[3] = itob( fake_subq_local[0] );
- cdr.Result[4] = itob( fake_subq_local[1] );
- cdr.Result[5] = itob( fake_subq_local[2] );
-
- cdr.Result[4] |= 0x80;
-
- report_time = 0;
- }
-
- cdr.Result[6] = 0;
- cdr.Result[7] = 0;
- }
-
-
- // Rayman: Logo freeze (resultready + dataready)
- cdr.ResultReady = 1;
- cdr.Stat = DataReady;
-
- SetResultSize(8);
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-}
-
-
-void cdrPlayInterrupt()
-{
- if( !cdr.Play ) return;
-
- //////////////////////////////////////////
- //////////////////////////////////////////
-
-#ifdef CDR_LOG
- CDR_LOG( "CDDA - %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
-
- {
- u8 temp[3];
-
- temp[0] = itob(cdr.SetSectorPlay[0]);
- temp[1] = itob(cdr.SetSectorPlay[1]);
- temp[2] = itob(cdr.SetSectorPlay[2]);
-
- // get subq
- CDR_readTrack( temp );
- }
-
- if( CDR_readCDDA ) {
- CDR_readCDDA( cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], cdr.Transfer );
-
- CDXA_Attenuation( (short *) cdr.Transfer, 2352, 1, CDDA_ATTENUATE );
- }
-
-
-
- // mute data track
- if( (Config.Cdda) ||
- (CDR_getStatus(&stat) != -1 && stat.Type == 1 && cdr.CurTrack == 1) )
- memset( cdr.Transfer, 0, CD_FRAMESIZE_RAW );
-
-
- if( SPU_playCDDAchannel)
- SPU_playCDDAchannel((short *)cdr.Transfer, CD_FRAMESIZE_RAW);
-
- CDRPLAY_INT( cdReadTime );
-
- //////////////////////////////////////////
- //////////////////////////////////////////
-
- subq = (struct SubQ *)CDR_getBufferSub();
- if (subq == NULL )
- Create_Fake_Subq();
-
- cdrPlayInterrupt_Autopause();
- cdrPlayInterrupt_Repplay();
-
- //////////////////////////////////////////
- //////////////////////////////////////////
-
- cdr.SetSectorPlay[2]++;
- if (cdr.SetSectorPlay[2] == 75) {
- cdr.SetSectorPlay[2] = 0;
- cdr.SetSectorPlay[1]++;
- if (cdr.SetSectorPlay[1] == 60) {
- cdr.SetSectorPlay[1] = 0;
- cdr.SetSectorPlay[0]++;
- }
- }
-
-
- Check_Shell(0);
-}
-
-
-void cdrInterrupt() {
- int i;
- unsigned char Irq = cdr.Irq;
-
- // Reschedule IRQ
- if (cdr.Stat) {
- CDR_INT( 0x100 );
- return;
- }
-
- cdr.Irq = 0xff;
- cdr.Ctrl &= ~0x80;
-
- switch (Irq) {
- case CdlSync:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlNop:
- SetResultSize(1);
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
-
- if (cdr.LidCheck == 0) cdr.LidCheck = 0x20;
- break;
-
- case CdlSetloc:
- cdr.CmdProcess = 0;
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlPlay:
- fake_subq_change = 0;
-
- if( cdr.Seeked == FALSE ) {
- memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 );
- cdr.Seeked = TRUE;
- }
-
- /*
- Rayman: detect track changes
- - fixes logo freeze
-
- Twisted Metal 2: skip PREGAP + starting accurate SubQ
- - plays tracks without retry play
-
- Wild 9: skip PREGAP + starting accurate SubQ
- - plays tracks without retry play
- */
- Set_Track();
- Find_CurTrack();
- ReadTrack( cdr.SetSectorPlay );
-
- // Chronicles of the Sword - getlocp timing
- Create_Fake_Subq();
-
- // GameShark CD Player: Calls 2x + Play 2x
- if( cdr.FastBackward || cdr.FastForward ) {
- if( cdr.FastForward ) cdr.FastForward--;
- if( cdr.FastBackward ) cdr.FastBackward--;
-
- if( cdr.FastBackward == 0 && cdr.FastForward == 0 ) {
- if( cdr.Play && CDR_getStatus(&stat) != -1 ) {
- cdr.SetSectorPlay[0] = stat.Time[0];
- cdr.SetSectorPlay[1] = stat.Time[1];
- cdr.SetSectorPlay[2] = stat.Time[2];
- }
- }
- }
-
-
- if (!Config.Cdda) {
- // BIOS CD Player
- // - Pause player, hit Track 01/02/../xx (Setloc issued!!)
-
- // GameShark CD Player: Resume play
- if( cdr.ParamC == 0 ) {
-#ifdef CDR_LOG___0
- CDR_LOG( "PLAY Resume @ %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
- //CDR_play( cdr.SetSectorPlay );
- }
- else
- {
- // BIOS CD Player: Resume play
- if( cdr.Param[0] == 0 ) {
-#ifdef CDR_LOG___0
- CDR_LOG( "PLAY Resume T0 @ %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
- //CDR_play( cdr.SetSectorPlay );
- }
- else {
-#ifdef CDR_LOG___0
- CDR_LOG( "PLAY Resume Td @ %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
- // BIOS CD Player: Allow track replaying
- StopCdda();
-
-
- cdr.CurTrack = btoi( cdr.Param[0] );
-
- if (CDR_getTN(cdr.ResultTN) != -1) {
- // check last track
- if (cdr.CurTrack > cdr.ResultTN[1])
- cdr.CurTrack = cdr.ResultTN[1];
-
- if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) {
- cdr.SetSectorPlay[0] = cdr.ResultTD[2];
- cdr.SetSectorPlay[1] = cdr.ResultTD[1];
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
-
- // reset data
- Set_Track();
- Find_CurTrack();
- ReadTrack( cdr.SetSectorPlay );
-
- //CDR_play(cdr.SetSectorPlay);
- }
- }
- }
- }
- }
-
-
- // Vib Ribbon: gameplay checks flag
- cdr.StatP &= ~STATUS_SEEK;
-
-
- cdr.CmdProcess = 0;
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
-
- cdr.StatP |= STATUS_PLAY;
-
-
- // BIOS player - set flag again
- cdr.Play = TRUE;
-
- CDRPLAY_INT( cdReadTime );
- break;
-
- case CdlForward:
- cdr.CmdProcess = 0;
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
-
-
- // GameShark CD Player: Calls 2x + Play 2x
- if( cdr.FastForward == 0 ) cdr.FastForward = 2;
- else cdr.FastForward++;
-
- cdr.FastBackward = 0;
- break;
-
- case CdlBackward:
- cdr.CmdProcess = 0;
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
-
-
- // GameShark CD Player: Calls 2x + Play 2x
- if( cdr.FastBackward == 0 ) cdr.FastBackward = 2;
- else cdr.FastBackward++;
-
- cdr.FastForward = 0;
- break;
-
- case CdlStandby:
- cdr.CmdProcess = 0;
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
- break;
-
- case CdlStop:
- cdr.CmdProcess = 0;
- SetResultSize(1);
- cdr.StatP &= ~STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
-// cdr.Stat = Acknowledge;
-
- if (cdr.LidCheck == 0) cdr.LidCheck = 0x20;
- break;
-
- case CdlPause:
- SetResultSize(1);
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- /*
- Gundam Battle Assault 2: much slower (*)
- - Fixes boot, gameplay
-
- Hokuto no Ken 2: slower
- - Fixes intro + subtitles
-
- InuYasha - Feudal Fairy Tale: slower
- - Fixes battles
- */
- AddIrqQueue(CdlPause + 0x20, cdReadTime * 3);
- cdr.Ctrl |= 0x80;
- break;
-
- case CdlPause + 0x20:
- SetResultSize(1);
- cdr.StatP &= ~STATUS_READ;
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
- break;
-
- case CdlInit:
- SetResultSize(1);
- cdr.StatP = STATUS_ROTATING;
- 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 |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlDemute:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlSetfilter:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlSetmode:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlGetmode:
- SetResultSize(6);
- cdr.StatP |= STATUS_ROTATING;
- 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] = cdr.Transfer[i];
- cdr.Stat = Acknowledge;
- break;
-
- case CdlGetlocP:
- // GameShark CDX CD Player: uses 17 bytes output (wraps around)
- SetResultSize(17);
- memset( cdr.Result, 0, 16 );
-
- 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);
-
-
- // subQ integrity check - data only (skip audio)
- if( subq->TrackNumber == 1 && stat.Type == 0x01 ) {
- if (calcCrc((u8 *)subq + 12, 10) != (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
- memset(cdr.Result + 2, 0, 3 + 3); // CRC wrong, wipe out time data
- }
- }
- } else {
- if( cdr.Play == FALSE ) Create_Fake_Subq();
-
-
- // track # / index #
- cdr.Result[0] = itob(cdr.CurTrack);
- cdr.Result[1] = itob(fake_subq_index);
-
- // local
- cdr.Result[2] = itob( fake_subq_local[0] );
- cdr.Result[3] = itob( fake_subq_local[1] );
- cdr.Result[4] = itob( fake_subq_local[2] );
-
- // absolute
- cdr.Result[5] = itob( fake_subq_real[0] );
- cdr.Result[6] = itob( fake_subq_real[1] );
- cdr.Result[7] = itob( fake_subq_real[2] );
- }
-
- // redump.org - wipe time
- if( !cdr.Play && CheckSBI(cdr.Result+5) ) {
- memset( cdr.Result+2, 0, 6 );
- }
-
- cdr.Stat = Acknowledge;
- break;
-
- case CdlGetTN:
- // 5-Star Racing: don't stop CDDA
- //
- // Vib Ribbon: CD swap
- StopReading();
-
- cdr.CmdProcess = 0;
- SetResultSize(3);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- if (CDR_getTN(cdr.ResultTN) == -1) {
- cdr.Stat = DiskError;
- cdr.Result[0] |= STATUS_ERROR;
- } else {
- cdr.Stat = Acknowledge;
- cdr.Result[1] = itob(cdr.ResultTN[0]);
- cdr.Result[2] = itob(cdr.ResultTN[1]);
- }
- break;
-
- case CdlGetTD:
- cdr.CmdProcess = 0;
- cdr.Track = btoi(cdr.Param[0]);
- SetResultSize(4);
- cdr.StatP |= STATUS_ROTATING;
- if (CDR_getTD(cdr.Track, cdr.ResultTD) == -1) {
- cdr.Stat = DiskError;
- cdr.Result[0] |= STATUS_ERROR;
- } else {
- cdr.Stat = Acknowledge;
- cdr.Result[0] = cdr.StatP;
- cdr.Result[1] = itob(cdr.ResultTD[2]);
- cdr.Result[2] = itob(cdr.ResultTD[1]);
- cdr.Result[3] = itob(cdr.ResultTD[0]);
- }
- break;
-
- case CdlSeekL:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.StatP |= STATUS_SEEK;
- cdr.Stat = Acknowledge;
-
- /*
- Crusaders of Might and Magic = 0.5x-4x
- - fix cutscene speech start
-
- Eggs of Steel = 2x-?
- - fix new game
-
- Medievil = ?-4x
- - fix cutscene speech
-
- Rockman X5 = 0.5-4x
- - fix capcom logo
- */
- AddIrqQueue(CdlSeekL + 0x20, cdReadTime * 4);
- break;
-
- case CdlSeekL + 0x20:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.StatP &= ~STATUS_SEEK;
- cdr.Result[0] = cdr.StatP;
- cdr.Seeked = TRUE;
- cdr.Stat = Complete;
-
-
- // Mega Man Legends 2: must update read cursor for getlocp
- ReadTrack( cdr.SetSector );
- break;
-
- case CdlSeekP:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.StatP |= STATUS_SEEK;
- cdr.Stat = Acknowledge;
- AddIrqQueue(CdlSeekP + 0x20, cdReadTime * 1);
- break;
-
- case CdlSeekP + 0x20:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.StatP &= ~STATUS_SEEK;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
- cdr.Seeked = TRUE;
-
- // GameShark Music Player
- memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 );
-
- // Tomb Raider 2: must update read cursor for getlocp
- Find_CurTrack();
- ReadTrack( cdr.SetSectorPlay );
- 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 |= STATUS_ROTATING;
- 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] = 0x80; // 0x80 leads to the menu in the bios, else loads CD
- }
- else {
- if (stat.Type == 2) {
- // Music CD
- cdr.Result[0] = 0x08;
- cdr.Result[1] = 0x10;
-
- cdr.Result[1] |= 0x80;
- }
- else {
- // Data CD
- if (CdromId[0] == '\0') {
- cdr.Result[0] = 0x00;
- cdr.Result[1] = 0x80;
- }
- else {
- cdr.Result[0] = 0x08;
- cdr.Result[1] = 0x00;
- }
- }
- }
-
- 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 = STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case CdlReadT:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- AddIrqQueue(CdlReadT + 0x20, 0x800);
- break;
-
- case CdlReadT + 0x20:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
- break;
-
- case CdlReadToc:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- AddIrqQueue(CdlReadToc + 0x20, 0x800);
- break;
-
- case CdlReadToc + 0x20:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- 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, 0x800);
- break;
-
- case READ_ACK:
- if (!cdr.Reading) return;
-
-
- // Fighting Force 2 - update subq time immediately
- // - fixes new game
- ReadTrack( cdr.SetSector );
-
-
- // Crusaders of Might and Magic - update getlocl now
- // - fixes cutscene speech
- {
- u8 *buf = CDR_getBuffer();
- memcpy(cdr.Transfer, buf, 8);
- }
-
-
- /*
- Duke Nukem: Land of the Babes - seek then delay read for one frame
- - fixes cutscenes
- */
-
- if (!cdr.Seeked) {
- cdr.Seeked = TRUE;
-
- cdr.StatP |= STATUS_SEEK;
- cdr.StatP &= ~STATUS_READ;
-
- // Crusaders of Might and Magic - use short time
- // - fix cutscene speech (startup)
-
- // ??? - use more accurate seek time later
- CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1);
- } else {
- cdr.StatP |= STATUS_READ;
- cdr.StatP &= ~STATUS_SEEK;
-
- CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1);
- }
-
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
-
- case 0xff:
- return;
-
- default:
- cdr.Stat = Complete;
- break;
- }
-
- Check_Shell( Irq );
-
- if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) {
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
-
-#ifdef CDR_LOG
- CDR_LOG("cdrInterrupt() Log: CDR Interrupt IRQ %x\n", Irq);
-#endif
-}
-
-void cdrReadInterrupt() {
- u8 *buf;
-
- if (!cdr.Reading)
- return;
-
- if (cdr.Irq || cdr.Stat) {
- CDREAD_INT(0x100);
- return;
- }
-
-#ifdef CDR_LOG
- CDR_LOG("cdrReadInterrupt() Log: KEY END");
-#endif
-
- cdr.OCUP = 1;
- SetResultSize(1);
- cdr.StatP |= STATUS_READ|STATUS_ROTATING;
- cdr.StatP &= ~STATUS_SEEK;
- cdr.Result[0] = cdr.StatP;
-
- ReadTrack( cdr.SetSector );
-
- buf = CDR_getBuffer();
- if (buf == NULL)
- cdr.RErr = -1;
-
- if (cdr.RErr == -1) {
-#ifdef CDR_LOG
- fprintf(emuLog, "cdrReadInterrupt() Log: err\n");
-#endif
- memset(cdr.Transfer, 0, DATA_SIZE);
- cdr.Stat = DiskError;
- cdr.Result[0] |= STATUS_ERROR;
- CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
- return;
- }
-
- memcpy(cdr.Transfer, buf, DATA_SIZE);
- CheckPPFCache(cdr.Transfer, cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
-
-
-#ifdef CDR_LOG
- fprintf(emuLog, "cdrReadInterrupt() Log: cdr.Transfer %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);
-#endif
-
- if ((!cdr.Muted) && (cdr.Mode & MODE_STRSND) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA
- // Firemen 2: Multi-XA files - briefings, cutscenes
- if( cdr.FirstSector == 1 && (cdr.Mode & MODE_SF)==0 ) {
- cdr.File = cdr.Transfer[4 + 0];
- cdr.Channel = cdr.Transfer[4 + 1];
- }
-
- if((cdr.Transfer[4 + 2] & 0x4) &&
- (cdr.Transfer[4 + 1] == cdr.Channel) &&
- (cdr.Transfer[4 + 0] == cdr.File)) {
- int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
-
- if (!ret) {
-#if 0
- int xa_type;
-
- // save - set only for FirstSector
- xa_type = cdr.Xa.stereo;
-
-
- // Duke Nukem - Time to Kill - speech, music volume control
- // Tekken 3 - post-match fade out
- if( cdr.Xa.stereo == 0 )
- CDXA_Attenuation( cdr.Xa.pcm, cdr.Xa.nsamples * 2, cdr.Xa.stereo, XA_ATTENUATE );
- else
- CDXA_Attenuation( cdr.Xa.pcm, cdr.Xa.nsamples * 4, cdr.Xa.stereo, XA_ATTENUATE );
-
-
- // fix mono xa attenuation
- if( cdr.Xa.stereo == 0 ) cdr.Xa.stereo = 1;
-#endif
-
- SPU_playADPCMchannel(&cdr.Xa);
- cdr.FirstSector = 0;
-
-
-#if 0
- cdr.Xa.stereo = xa_type;
-#endif
-
-
-#if 0
- // Crash Team Racing: music, speech
- // - done using cdda decoded buffer (spu irq)
- // - don't do here
-
- // signal ADPCM data ready
- psxHu32ref(0x1070) |= SWAP32((u32)0x200);
-#endif
- }
- 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;
-
- // G-Police: Don't autopause ADPCM even if mode set (music)
- if ((cdr.Transfer[4 + 2] & 0x80) && (cdr.Mode & MODE_AUTOPAUSE) &&
- (cdr.Transfer[4 + 2] & 0x4) != 0x4 ) { // EOF
-#ifdef CDR_LOG
- CDR_LOG("cdrReadInterrupt() Log: Autopausing read\n");
-#endif
-// AddIrqQueue(AUTOPAUSE, 0x2000);
- AddIrqQueue(CdlPause, 0x2000);
- }
- else {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
- }
-
- /*
- Croc 2: $40 - only FORM1 (*)
- Judge Dredd: $C8 - only FORM1 (*)
- Sim Theme Park - no adpcm at all (zero)
- */
-
- if( (cdr.Mode & MODE_STRSND) == 0 || (cdr.Transfer[4+2] & 0x4) != 0x4 ) {
- cdr.Stat = DataReady;
- } else {
- // Breath of Fire 3 - fix inn sleeping
- // Rockman X5 - no music restart problem
- cdr.Stat = NoIntr;
- }
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
- Check_Shell(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
-*/
-
-unsigned char 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("cdrRead0() 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(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite0() 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;
- }
-
- // Tekken: CDXA fade-out
- else if( rt == 2 ) {
- //cdr.AttenuatorLeft[0] = 0;
- //cdr.AttenuatorLeft[1] = 0;
- }
- else if( rt == 3 ) {
- // Tekken 3 - character menu (don't do this!)
- //cdr.AttenuatorRight[0] = 0;
- //cdr.AttenuatorRight[1] = 0;
- }
-}
-
-unsigned char cdrRead1(void) {
- if (cdr.ResultReady) { // && cdr.Ctrl & 0x1) {
- // GameShark CDX CD Player: uses 17 bytes output (wraps around)
- psxHu8(0x1801) = cdr.Result[cdr.ResultP & 0xf];
- cdr.ResultP++;
- if (cdr.ResultP == cdr.ResultC)
- cdr.ResultReady = 0;
- } else {
- psxHu8(0x1801) = 0;
- }
-#ifdef CDR_LOG
- CDR_LOG("cdrRead1() Log: CD1 Read: %x\n", psxHu8(0x1801));
-#endif
- return psxHu8(0x1801);
-}
-
-void cdrWrite1(unsigned char rt) {
- int i;
-
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: CD1 write: %x (%s)\n", rt, CmdName[rt]);
-#endif
-
-
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 3 ) {
- cdr.AttenuatorRight[0] = rt;
- }
-
-
- // psxHu8(0x1801) = rt;
- cdr.Cmd = rt;
- cdr.OCUP = 0;
-
-#ifdef CDRCMD_DEBUG
- SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]);
- if (cdr.ParamC) {
- SysPrintf(" Param[%d] = {", cdr.ParamC);
- for (i = 0; i < cdr.ParamC; i++)
- SysPrintf(" %x,", cdr.Param[i]);
- SysPrintf("}\n");
- } else {
- SysPrintf("\n");
- }
-#endif
-
- if (cdr.Ctrl & 0x1) return;
-
- switch (cdr.Cmd) {
- case CdlSync:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlNop:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Twisted Metal 3 - fix music
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlSetloc:
- StopReading();
- cdr.Seeked = FALSE;
- for (i = 0; i < 3; i++)
- cdr.SetSector[i] = btoi(cdr.Param[i]);
- cdr.SetSector[3] = 0;
-
-#ifdef DVD5_HACK
- // PS1 DVD5 hack (shalma's disc combining kits)
- dvd5_mode = cdr.Param[2] & 0x80;
-
- if( CDR__setDVD5 ) {
- if( cdr.Param[2] & 0x80 )
- CDR__setDVD5(1);
- else if( cdr.Param[1] & 0x80 )
- CDR__setDVD5(2);
- else
- CDR__setDVD5(0);
- }
-
- cdr.Param[1] &= 0x7f;
- cdr.Param[2] &= 0x7f;
-#endif
-
- /*
- if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) {
- *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek;
- }*/
-
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlPlay:
- // Vib Ribbon: try same track again
- StopCdda();
-
- // Vib Ribbon - decoded buffer IRQ for CDDA reading
- // - fixes ribbon timing + music CD mode
- CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
-
-
- cdr.Play = TRUE;
-
- cdr.StatP |= STATUS_SEEK;
- cdr.StatP &= ~STATUS_ROTATING;
-
- 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, 0x800);
- break;
-
- case CdlStandby:
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlStop:
- // GameShark CD Player: Reset CDDA to track start
- if( cdr.Play && CDR_getStatus(&stat) != -1 ) {
- cdr.SetSectorPlay[0] = stat.Time[0];
- cdr.SetSectorPlay[1] = stat.Time[1];
- cdr.SetSectorPlay[2] = stat.Time[2];
-
- Find_CurTrack();
-
-
- // grab time for current track
- CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
-
- cdr.SetSectorPlay[0] = cdr.ResultTD[2];
- cdr.SetSectorPlay[1] = cdr.ResultTD[1];
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
- }
-
- StopCdda();
- StopReading();
-
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlPause:
- /*
- GameShark CD Player: save time for resume
-
- Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors
- */
-
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlReset:
- case CdlInit:
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlMute:
- cdr.Muted = TRUE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
-
- // Duke Nukem - Time to Kill
- // - do not directly set cd-xa volume
- //SPU_writeRegister( H_CDLeft, 0x0000 );
- //SPU_writeRegister( H_CDRight, 0x0000 );
- break;
-
- case CdlDemute:
- cdr.Muted = FALSE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
-
- // Duke Nukem - Time to Kill
- // - do not directly set cd-xa volume
- //SPU_writeRegister( H_CDLeft, 0x7f00 );
- //SPU_writeRegister( H_CDRight, 0x7f00 );
- 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("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]);
-#endif
- cdr.Mode = cdr.Param[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
-
- // Squaresoft on PlayStation 1998 Collector's CD Vol. 1
- // - fixes choppy movie sound
- if( cdr.Play && (cdr.Mode & MODE_CDDA) == 0 )
- StopCdda();
- break;
-
- case CdlGetmode:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlGetlocL:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Crusaders of Might and Magic - cutscene speech
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlGetlocP:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // GameShark CDX / Lite Player: pretty narrow time window
- // - doesn't always work due to time inprecision
- //AddIrqQueue(cdr.Cmd, 0x28);
-
- // Tomb Raider 2 - cdda
- AddIrqQueue(cdr.Cmd, 0x40);
- break;
-
- case CdlGetTN:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- //AddIrqQueue(cdr.Cmd, 0x800);
-
- // GameShark CDX CD Player: very long time
- AddIrqQueue(cdr.Cmd, 0x100000);
- break;
-
- case CdlGetTD:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlSeekL:
-// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
-
- StopCdda();
- StopReading();
-
- break;
-
- case CdlSeekP:
-// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Tomb Raider 2 - reset cdda
- StopCdda();
- StopReading();
-
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- // Destruction Derby: read TOC? GetTD after this
- case CdlReadT:
- 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, 0x800);
- break;
-
- case CdlReadToc:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- default:
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
-#endif
- return;
- }
- if (cdr.Stat != NoIntr) {
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
-}
-
-unsigned char cdrRead2(void) {
- unsigned char ret;
-
- if (cdr.Readed == 0) {
- ret = 0;
- } else {
- ret = cdr.Transfer[cdr.transferIndex];
- cdr.transferIndex++;
- adjustTransferIndex();
- }
-
-#ifdef CDR_LOG
- CDR_LOG("cdrRead2() Log: CD2 Read: %x\n", ret);
-#endif
- return ret;
-}
-
-void cdrWrite2(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite2() Log: CD2 write: %x\n", rt);
-#endif
-
-
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 2 ) {
- cdr.AttenuatorLeft[0] = rt;
- }
- else if( (cdr.Ctrl & 3) == 3 ) {
- cdr.AttenuatorRight[1] = rt;
- }
-
-
-
- if (cdr.Ctrl & 0x1) {
- switch (rt) {
- case 0x07:
- cdr.ParamP = 0;
- cdr.ParamC = 0;
- cdr.ResultReady = 1; //0;
- cdr.Ctrl &= ~3; //cdr.Ctrl = 0;
- break;
-
- default:
- cdr.Reg2 = rt;
- break;
- }
- } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) {
- cdr.Param[cdr.ParamP++] = rt;
- cdr.ParamC++;
- }
-}
-
-unsigned char 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("cdrRead3() Log: CD3 Read: %x\n", psxHu8(0x1803));
-#endif
- return psxHu8(0x1803);
-}
-
-void cdrWrite3(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt);
-#endif
-
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 2 ) {
- cdr.AttenuatorLeft[1] = rt;
- }
- else if( (cdr.Ctrl & 3) == 3 && rt == 0x20 ) {
-#ifdef CDR_LOG
- CDR_LOG( "CD-XA Volume: %X %X | %X %X\n",
- cdr.AttenuatorLeft[0], cdr.AttenuatorLeft[1],
- cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] );
-#endif
- }
-
-
- // GameShark CDX CD Player: Irq timing mania
- if( rt == 0 &&
- cdr.Irq != 0 && cdr.Irq != 0xff &&
- cdr.ResultReady == 0 ) {
-
- // GS CDX: ~0x28 cycle timing - way too precise
- if( cdr.Irq == CdlGetlocP ) {
- cdrInterrupt();
-
- psxRegs.interrupt &= ~(1 << PSXINT_CDR);
- }
- }
-
-
- if (rt == 0x07 && cdr.Ctrl & 0x1) {
- cdr.Stat = 0;
-
- if (cdr.Irq == 0xff) {
- cdr.Irq = 0;
- return;
- }
-
-#if 0
- if (cdr.Reading && !cdr.ResultReady) {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
- }
-#else
- // XA streaming - incorrect timing because of this reschedule
- // - Final Fantasy Tactics
- // - various other games
-
- /*
- if (cdr.Reading && !cdr.ResultReady) {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
- }
- */
-#endif
-
- return;
- }
-
- if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) {
- cdr.Readed = 1;
- cdr.transferIndex = 0;
-
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- case MODE_SIZE_2328:
- case MODE_SIZE_2048:
- cdr.transferIndex += 12;
- break;
-
- case MODE_SIZE_2340:
- cdr.transferIndex += 0;
- break;
-
- default:
- break;
- }
- }
-}
-
-void psxDma3(u32 madr, u32 bcr, u32 chcr) {
- u32 cdsize;
- u8 *ptr/*, *cdwrap_ptr*/;
-
-#ifdef CDR_LOG
- CDR_LOG("psxDma3() Log: *** DMA 3 *** %x addr = %x size = %x\n", chcr, madr, bcr);
-#endif
-
- switch (chcr) {
- case 0x11000000:
- case 0x11400100:
- if (cdr.Readed == 0) {
-#ifdef CDR_LOG
- CDR_LOG("psxDma3() Log: *** DMA 3 *** NOT READY\n");
-#endif
- break;
- }
-
- cdsize = (bcr & 0xffff) * 4;
-
- // Ape Escape: bcr = 0001 / 0000
- // - fix boot
- if( cdsize == 0 )
- {
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- case MODE_SIZE_2340: cdsize = 2340; break;
- case MODE_SIZE_2328: cdsize = 2328; break;
- case MODE_SIZE_2048: cdsize = 2048; break;
- }
- }
-
-
- ptr = (u8 *)PSXM(madr);
- if (ptr == NULL) {
-#ifdef CPU_LOG
- CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n");
-#endif
- break;
- }
-
-/*
-#if 1
-
- // GS CDX: Enhancement CD crash
- // - Setloc 0:0:0
- // - CdlPlay
- // - Spams DMA3 and gets buffer overrun
-
- if( (cdr.pTransfer-cdr.Transfer) + cdsize > 2352 )
- {
- // avoid crash - probably should wrap here
- //memcpy(ptr, cdr.pTransfer, cdsize);
- }
- else
- {
- memcpy(ptr, cdr.pTransfer, cdsize);
- }
-
- psxCpu->Clear(madr, cdsize / 4);
- cdr.pTransfer += cdsize;
-#else
- cdwrap_ptr = cdr.Transfer;
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- case MODE_SIZE_2340: cdwrap_ptr += 2340; break;
- case MODE_SIZE_2328: cdwrap_ptr += 12 + 2328; break;
- case MODE_SIZE_2048: cdwrap_ptr += 12 + 2048; break;
- }
-
-
- // fast copy - no wrap
- if( cdr.pTransfer + cdsize <= cdwrap_ptr ) {
- memcpy(ptr, cdr.pTransfer, cdsize);
-
- psxCpu->Clear(madr, cdsize / 4);
- cdr.pTransfer += cdsize;
- } else {
- int lcv;
-
- // CDROM wrapping
- //
- // Ape Escape - used several times
- // Gameshark Lite - opening movie
- //
- // Gameshark CDX: enhancement CD patcher
- // - calls CdlPlay @ 0:2:0
- // - spams DMA3 and overruns buffer
-
- for( lcv = 0; lcv < cdsize; lcv++ )
- {
- // wrap cdrom ptr
- if( cdr.pTransfer == cdwrap_ptr ) {
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- case MODE_SIZE_2328:
- case MODE_SIZE_2048:
- cdr.pTransfer = cdr.Transfer + 12;
- break;
-
- case MODE_SIZE_2340:
- cdr.pTransfer = cdr.Transfer + 0;
- break;
- }
- }
-
-
- *(ptr+lcv) = *cdr.pTransfer;
-
- cdr.pTransfer++;
- }
-
- psxCpu->Clear(madr, cdsize / 4);
- }
-#endif
-*/
- {
- int i;
-
- for(i = 0; i < cdsize; ++i) {
- ptr[i] = cdr.Transfer[cdr.transferIndex];
- cdr.transferIndex++;
- adjustTransferIndex();
- }
-
- psxCpu->Clear(madr, cdsize / 4);
- }
-
- // burst vs normal
- if( chcr == 0x11400100 ) {
-#if 1
- CDRDMA_INT( (cdsize/4) / 4 );
-#else
- // Experimental burst dma transfer (0.333x max)
- CDRDMA_INT( (cdsize/4) / 3 );
-#endif
- }
- else if( chcr == 0x11000000 ) {
- CDRDMA_INT( (cdsize/4) * 1 );
- }
- return;
-
- default:
-#ifdef CDR_LOG
- CDR_LOG("psxDma3() Log: Unknown cddma %x\n", chcr);
-#endif
- break;
- }
-
- HW_DMA3_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(3);
-}
-
-void cdrDmaInterrupt()
-{
- HW_DMA3_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(3);
-}
-
-void cdrReset() {
- memset(&cdr, 0, sizeof(cdr));
- cdr.CurTrack = 1;
- cdr.File = 1;
- cdr.Channel = 1;
-
-#if 0
- // BIOS player - default values
- cdr.AttenuatorLeft[0] = 0x80;
- cdr.AttenuatorLeft[1] = 0x00;
- cdr.AttenuatorRight[0] = 0x80;
- cdr.AttenuatorRight[1] = 0x00;
-#endif
-}
-
-int cdrFreeze(gzFile f, int Mode) {
- unsigned int tmp;
-
-
- if( Mode == 0 ) {
- StopCdda();
- }
-
-
- gzfreeze(&cdr, sizeof(cdr));
-
-
-
- if (Mode == 1)
- tmp = cdr.transferIndex;
-
- gzfreeze(&tmp, sizeof(tmp));
-
- if (Mode == 0)
- cdr.transferIndex = tmp;
-
- return 0;
-}
-
-void LidInterrupt() {
- cdr.LidCheck = 0x20; // start checker
-
- CDRLID_INT( cdReadTime * 3 );
-
- // generate interrupt if none active - open or close
- if (cdr.Irq == 0 || cdr.Irq == 0xff) {
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(CdlNop, 0x800);
- }
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* Handles all CD-ROM registers and functions. +*/ + +#include "cdrom.h" +#include "ppf.h" +#include "psxdma.h" + +cdrStruct cdr; + +/* CD-ROM magic numbers */ +#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 CdlReadT 18 +#define CdlGetTN 19 +#define CdlGetTD 20 +#define CdlSeekL 21 +#define CdlSeekP 22 +#define CdlSetclock 23 +#define CdlGetclock 24 +#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", "CdlReadT", "CdlGetTN", + "CdlGetTD", "CdlSeekL", "CdlSeekP", "CdlSetclock", + "CdlGetclock", "CdlTest", "CdlID", "CdlReadS", + "CdlReset", NULL, "CDlReadToc", NULL +}; + +unsigned char Test04[] = { 0 }; +unsigned char Test05[] = { 0 }; +unsigned char Test20[] = { 0x98, 0x06, 0x10, 0xC3 }; +unsigned char Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F }; +unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; + +// cdr.Stat: +#define NoIntr 0 +#define DataReady 1 +#define Complete 2 +#define Acknowledge 3 +#define DataEnd 4 +#define DiskError 5 + +/* Modes flags */ +#define MODE_SPEED (1<<7) // 0x80 +#define MODE_STRSND (1<<6) // 0x40 ADPCM on/off +#define MODE_SIZE_2340 (1<<5) // 0x20 +#define MODE_SIZE_2328 (1<<4) // 0x10 +#define MODE_SIZE_2048 (0<<4) // 0x00 +#define MODE_SF (1<<3) // 0x08 channel on/off +#define MODE_REPORT (1<<2) // 0x04 +#define MODE_AUTOPAUSE (1<<1) // 0x02 +#define MODE_CDDA (1<<0) // 0x01 + +/* Status flags */ +#define STATUS_PLAY (1<<7) // 0x80 +#define STATUS_SEEK (1<<6) // 0x40 +#define STATUS_READ (1<<5) // 0x20 +#define STATUS_SHELLOPEN (1<<4) // 0x10 +#define STATUS_UNKNOWN3 (1<<3) // 0x08 +#define STATUS_UNKNOWN2 (1<<2) // 0x04 +#define STATUS_ROTATING (1<<1) // 0x02 +#define STATUS_ERROR (1<<0) // 0x01 + +#define XA_ATTENUATE 0 +#define CDDA_ATTENUATE 1 + +// 1x = 75 sectors per second +// PSXCLK = 1 sec in the ps +// so (PSXCLK / 75) = cdr read time (linuzappz) +#define cdReadTime (PSXCLK / 75) + +static struct CdrStat stat; +static struct SubQ *subq; + + +extern unsigned int msf2sec(char *msf); +extern void sec2msf(unsigned int s, char *msf); + + +extern u16 *iso_play_cdbuf; +extern u16 iso_play_bufptr; +extern long CALLBACK ISOinit(void); +extern void CALLBACK SPUirq(void); +extern SPUregisterCallback SPU_registerCallback; + +// A bit of a kludge, but it will get rid of the "macro redefined" warnings + +#ifdef H_SPUirqAddr +#undef H_SPUirqAddr +#endif + +#ifdef H_SPUaddr +#undef H_SPUaddr +#endif + +#ifdef H_SPUctrl +#undef H_SPUctrl +#endif + +#define H_SPUirqAddr 0x1f801da4 +#define H_SPUaddr 0x1f801da6 +#define H_SPUctrl 0x1f801daa +#define H_CDLeft 0x1f801db0 +#define H_CDRight 0x1f801db2 + + +#define CDR_INT(eCycle) { \ + psxRegs.interrupt |= (1 << PSXINT_CDR); \ + psxRegs.intCycle[PSXINT_CDR].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_CDR].sCycle = psxRegs.cycle; \ +} + +#define CDREAD_INT(eCycle) { \ + psxRegs.interrupt |= (1 << PSXINT_CDREAD); \ + psxRegs.intCycle[PSXINT_CDREAD].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_CDREAD].sCycle = psxRegs.cycle; \ +} + +#define CDRDBUF_INT(eCycle) { \ + psxRegs.interrupt |= (1 << PSXINT_CDRDBUF); \ + psxRegs.intCycle[PSXINT_CDRDBUF].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_CDRDBUF].sCycle = psxRegs.cycle; \ +} + +#define CDRLID_INT(eCycle) { \ + psxRegs.interrupt |= (1 << PSXINT_CDRLID); \ + psxRegs.intCycle[PSXINT_CDRLID].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_CDRLID].sCycle = psxRegs.cycle; \ +} + +#define CDRPLAY_INT(eCycle) { \ + psxRegs.interrupt |= (1 << PSXINT_CDRPLAY); \ + psxRegs.intCycle[PSXINT_CDRPLAY].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_CDRPLAY].sCycle = psxRegs.cycle; \ +} + +#define StartReading(type, eCycle) { \ + cdr.Reading = type; \ + cdr.FirstSector = 1; \ + cdr.Readed = 0xff; \ + AddIrqQueue(READ_ACK, eCycle); \ +} + +#define StopReading() { \ + if (cdr.Reading) { \ + cdr.Reading = 0; \ + psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); \ + } \ + cdr.StatP &= ~STATUS_READ;\ +} + +#define StopCdda() { \ + if (cdr.Play) { \ + if (!Config.Cdda) CDR_stop(); \ + cdr.StatP &= ~STATUS_PLAY; \ + cdr.Play = FALSE; \ + cdr.FastForward = 0; \ + cdr.FastBackward = 0; \ + SPU_registerCallback( SPUirq ); \ + } \ +} + +#define SetResultSize(size) { \ + cdr.ResultP = 0; \ + cdr.ResultC = size; \ + cdr.ResultReady = 1; \ +} + +void adjustTransferIndex() +{ + unsigned int bufSize = 0; + + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { + //Do we need a default case in this switch? + case MODE_SIZE_2340: bufSize = 2340; break; + case MODE_SIZE_2328: bufSize = 12 + 2328; break; + case MODE_SIZE_2048: bufSize = 12 + 2048; break; + } + + if (cdr.transferIndex >= bufSize) + { + if (bufSize == 0) { + //Make sure we don't divide by zero + //Do nothing + } else { + cdr.transferIndex %= bufSize; + } + } +} + +void cdrDecodedBufferInterrupt() +{ + u16 buf_ptr[0x400], lcv; + +#if 0 + return; +#endif + + + // ISO reader only + if( CDR_init != ISOinit ) return; + + + // check dbuf IRQ still active + if( cdr.Play == 0 ) return; + if( (SPU_readRegister( H_SPUctrl ) & 0x40) == 0 ) return; + if( (SPU_readRegister( H_SPUirqAddr ) * 8) >= 0x800 ) return; + + + + // turn off plugin SPU IRQ decoded buffer handling + SPU_registerCallback( 0 ); + + + + /* + Vib Ribbon + + 000-3FF = left CDDA + 400-7FF = right CDDA + + Assume IRQ every wrap + */ + + if( iso_play_cdbuf ) + { + for( lcv = 0; lcv < 0x200; lcv++ ) + { + // left + buf_ptr[ lcv ] = iso_play_cdbuf[ iso_play_bufptr ]; + + // right + buf_ptr[ lcv+0x200 ] = iso_play_cdbuf[ iso_play_bufptr+1 ]; + + iso_play_bufptr += 2; + } + } + else + { + memset( buf_ptr, 0, sizeof(buf_ptr) ); + } + + + // feed CDDA decoded buffer manually + SPU_writeRegister( H_SPUaddr,0 ); + SPU_writeDMAMem( buf_ptr, 0x800 / 2 ); + + + // signal CDDA data ready + psxHu32ref(0x1070) |= SWAP32((u32)0x200); + + + // time for next full buffer + //CDRDBUF_INT( PSXCLK / 44100 * 0x200 ); + CDRDBUF_INT( PSXCLK / 44100 * 0x100 ); +} + + +void cdrLidSeekInterrupt() +{ + // turn back on checking + if( cdr.LidCheck == 0x10 ) + { + cdr.LidCheck = 0; + } + + // official lid close + else if( cdr.LidCheck == 0x30 ) + { + // GS CDX 3.3: $13 + cdr.StatP |= STATUS_ROTATING; + + + // GS CDX 3.3 - ~50 getlocp tries + CDRLID_INT( cdReadTime * 3 ); + cdr.LidCheck = 0x40; + } + + // turn off ready + else if( cdr.LidCheck == 0x40 ) + { + // GS CDX 3.3: $01 + cdr.StatP &= ~STATUS_SHELLOPEN; + cdr.StatP &= ~STATUS_ROTATING; + + + // GS CDX 3.3 - ~50 getlocp tries + CDRLID_INT( cdReadTime * 3 ); + cdr.LidCheck = 0x50; + } + + // now seek + else if( cdr.LidCheck == 0x50 ) + { + // GameShark Lite: Start seeking ($42) + cdr.StatP |= STATUS_SEEK; + cdr.StatP |= STATUS_ROTATING; + cdr.StatP &= ~STATUS_ERROR; + + + CDRLID_INT( cdReadTime * 3 ); + cdr.LidCheck = 0x60; + } + + // done = cd ready + else if( cdr.LidCheck == 0x60 ) + { + // GameShark Lite: Seek detection done ($02) + cdr.StatP &= ~STATUS_SEEK; + + cdr.LidCheck = 0; + } +} + + +void Check_Shell( int Irq ) +{ + // check case open/close + if (cdr.LidCheck > 0) + { +#ifdef CDR_LOG + CDR_LOG( "LidCheck\n" ); +#endif + + // $20 = check lid state + if( cdr.LidCheck == 0x20 ) + { + u32 i; + + i = stat.Status; + if (CDR_getStatus(&stat) != -1) + { + // BIOS hangs + BIOS error messages + //if (stat.Type == 0xff) + //cdr.Stat = DiskError; + + // case now open + if (stat.Status & STATUS_SHELLOPEN) + { + // Vib Ribbon: pre-CD swap + StopCdda(); + + + // GameShark Lite: Death if DiskError happens + // + // Vib Ribbon: Needs DiskError for CD swap + + if (Irq != CdlNop) + { + cdr.Stat = DiskError; + + cdr.StatP |= STATUS_ERROR; + cdr.Result[0] |= STATUS_ERROR; + } + + // GameShark Lite: Wants -exactly- $10 + cdr.StatP |= STATUS_SHELLOPEN; + cdr.StatP &= ~STATUS_ROTATING; + + + CDRLID_INT( cdReadTime * 3 ); + cdr.LidCheck = 0x10; + + + // GS CDX 3.3 = $11 + } + + // case just closed + else if ( i & STATUS_SHELLOPEN ) + { + cdr.StatP |= STATUS_ROTATING; + + CheckCdrom(); + + + if( cdr.Stat == NoIntr ) + cdr.Stat = Acknowledge; + + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + + + // begin close-seek-ready cycle + CDRLID_INT( cdReadTime * 3 ); + cdr.LidCheck = 0x30; + + + // GameShark Lite: Wants -exactly- $42, then $02 + // GS CDX 3.3: Wants $11/$80, $13/$80, $01/$00 + } + + // case still closed - wait for recheck + else + { + CDRLID_INT( cdReadTime * 3 ); + cdr.LidCheck = 0x10; + } + } + } + + + // GS CDX: clear all values but #1,#2 + if( (cdr.LidCheck >= 0x30) || (cdr.StatP & STATUS_SHELLOPEN) ) + { + SetResultSize(16); + memset( cdr.Result, 0, 16 ); + + cdr.Result[0] = cdr.StatP; + + + // GS CDX: special return value + if( cdr.StatP & STATUS_SHELLOPEN ) + { + cdr.Result[1] = 0x80; + } + + + if( cdr.Stat == NoIntr ) + cdr.Stat = Acknowledge; + + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + } + } +} + + +void Find_CurTrack() { + cdr.CurTrack = 0; + + if (CDR_getTN(cdr.ResultTN) != -1) { + int lcv; + + for( lcv = 1; lcv <= cdr.ResultTN[1]; lcv++ ) { + if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) { + u32 sect1, sect2; + +#ifdef CDR_LOG___0 + CDR_LOG( "curtrack %d %d %d | %d %d %d | %d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], + cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0], + cdr.CurTrack ); +#endif + + // find next track boundary - only need m:s accuracy + sect1 = cdr.SetSectorPlay[0] * 60 * 75 + cdr.SetSectorPlay[1] * 75; + sect2 = cdr.ResultTD[2] * 60 * 75 + cdr.ResultTD[1] * 75; + + // Twisted Metal 4 - psx cdda pregap (2-sec) + // - fix in-game music + sect2 -= 75 * 2; + + if( sect1 >= sect2 ) { + cdr.CurTrack++; + continue; + } + } + + break; + } + } +} + +static void ReadTrack( u8 *time ) { + cdr.Prev[0] = itob( time[0] ); + cdr.Prev[1] = itob( time[1] ); + cdr.Prev[2] = itob( time[2] ); + +#ifdef CDR_LOG + CDR_LOG("ReadTrack() Log: KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); +#endif + cdr.RErr = CDR_readTrack(cdr.Prev); +} + + +static void CDXA_Attenuation( s16 *buf, int size, int stereo, int attenuate_type ) +{ + s16 *spsound; + s32 lc = 0, rc = 0; + int i; + + spsound = buf; + +#if 0 + // mono xa attenuation + // - Tales of Phantasia (voice meter) + if( stereo == 0 ) { + s16 temp[32768]; + int dst; + + dst = 0; + for( i = 0; i < size; i++, dst+=2 ) { + temp[dst+0] = spsound[i]; + temp[dst+1] = spsound[i]; + } + + size *= 2*2; + memcpy( spsound, temp, size ); + } +#endif + + for( i = 0; i < size / 2; i += 2 ) + { + // Chronicles of the Sword - cutscene (xa), speech (cdda) + if( attenuate_type == XA_ATTENUATE ) { + lc = (spsound[i+0] * cdr.AttenuatorLeft[0] + spsound[i+1] * cdr.AttenuatorLeft[1]) / 128; + rc = (spsound[i+1] * cdr.AttenuatorRight[0] + spsound[i+0] * cdr.AttenuatorRight[1]) / 128; + } else if( attenuate_type == CDDA_ATTENUATE ) { + lc = (spsound[i+0] * cdr.AttenuatorLeft[0] + spsound[i+1] * cdr.AttenuatorRight[1]) / 128; + rc = (spsound[i+1] * cdr.AttenuatorRight[0] + spsound[i+0] * cdr.AttenuatorLeft[1]) / 128; + } + + if( lc < -32768 ) lc = -32768; + if( rc < -32768 ) rc = -32768; + if( lc > 32767 ) lc = 32767; + if( rc > 32767 ) rc = 32767; + + spsound[i + 0] = lc; + spsound[i + 1] = rc; + } +} + + +void AddIrqQueue(unsigned char irq, unsigned long ecycle) { + cdr.Irq = irq; + cdr.eCycle = ecycle; + + // Doom: Force rescheduling + // - Fixes boot + CDR_INT(ecycle); +} + + +void Set_Track() +{ + if (CDR_getTN(cdr.ResultTN) != -1) { + int lcv; + + for( lcv = 1; lcv < cdr.ResultTN[1]; lcv++ ) { + if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) { +#ifdef CDR_LOG___0 + CDR_LOG( "settrack %d %d %d | %d %d %d | %d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], + cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0], + cdr.CurTrack ); +#endif + + // check if time matches track start (only need min, sec accuracy) + // - m:s:f vs f:s:m + if( cdr.SetSectorPlay[0] == cdr.ResultTD[2] && + cdr.SetSectorPlay[1] == cdr.ResultTD[1] ) { + // skip pregap frames + if( cdr.SetSectorPlay[2] < cdr.ResultTD[0] ) + cdr.SetSectorPlay[2] = cdr.ResultTD[0]; + + break; + } + else if( cdr.SetSectorPlay[0] < cdr.ResultTD[2] ) + break; + } + } + } +} + + +static u8 fake_subq_local[3], fake_subq_real[3], fake_subq_index, fake_subq_change; +void Create_Fake_Subq() +{ + u8 temp_cur[3], temp_next[3], temp_start[3], pregap; + int diff; + + if (CDR_getTN(cdr.ResultTN) == -1) return; + if( cdr.CurTrack+1 <= cdr.ResultTN[1] ) { + pregap = 150; + if( CDR_getTD(cdr.CurTrack+1, cdr.ResultTD) == -1 ) return; + } else { + // last track - cd size + pregap = 0; + if( CDR_getTD(0, cdr.ResultTD) == -1 ) return; + } + + if( cdr.Play == TRUE ) { + temp_cur[0] = cdr.SetSectorPlay[0]; + temp_cur[1] = cdr.SetSectorPlay[1]; + temp_cur[2] = cdr.SetSectorPlay[2]; + } else { + temp_cur[0] = btoi( cdr.Prev[0] ); + temp_cur[1] = btoi( cdr.Prev[1] ); + temp_cur[2] = btoi( cdr.Prev[2] ); + } + + fake_subq_real[0] = temp_cur[0]; + fake_subq_real[1] = temp_cur[1]; + fake_subq_real[2] = temp_cur[2]; + + temp_next[0] = cdr.ResultTD[2]; + temp_next[1] = cdr.ResultTD[1]; + temp_next[2] = cdr.ResultTD[0]; + + + // flag- next track + if( msf2sec(temp_cur) >= msf2sec( temp_next )-pregap ) { + fake_subq_change = 1; + + cdr.CurTrack++; + + // end cd + if( pregap == 0 ) StopCdda(); + } + + ////////////////////////////////////////////////// + ////////////////////////////////////////////////// + + // repair + if( cdr.CurTrack <= cdr.ResultTN[1] ) { + if( CDR_getTD(cdr.CurTrack, cdr.ResultTD) == -1 ) return; + } else { + // last track - cd size + if( CDR_getTD(0, cdr.ResultTD) == -1 ) return; + } + + temp_start[0] = cdr.ResultTD[2]; + temp_start[1] = cdr.ResultTD[1]; + temp_start[2] = cdr.ResultTD[0]; + + +#ifdef CDR_LOG + CDR_LOG( "CDDA FAKE SUB - %d:%d:%d / %d:%d:%d / %d:%d:%d\n", + temp_cur[0], temp_cur[1], temp_cur[2], + temp_start[0], temp_start[1], temp_start[2], + temp_next[0], temp_next[1], temp_next[2]); +#endif + + + + // local time - pregap / real + diff = msf2sec(temp_cur) - msf2sec( temp_start ); + if( diff < 0 ) { + fake_subq_index = 0; + + sec2msf( -diff, fake_subq_local ); + } else { + fake_subq_index = 1; + + sec2msf( diff, fake_subq_local ); + } +} + + +void cdrPlayInterrupt_Autopause() +{ + if ((cdr.Mode & (MODE_AUTOPAUSE|MODE_CDDA)) != (MODE_AUTOPAUSE|MODE_CDDA)) return; + + // Reschedule IRQ + if ( cdr.Irq || cdr.Stat ) { +#ifdef CDR_LOG + CDR_LOG("=== BUSY === cdrPlayInterrupt\n"); +#endif + + //CDRPLAY_INT( 0x800 ); + return; + } + + + if( CDR_getStatus(&stat) == -1) return; + + subq = (struct SubQ *)CDR_getBufferSub(); + + if (subq != NULL ) { +#ifdef CDR_LOG + CDR_LOG( "CDDA SUB - %X:%X:%X\n", + subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] ); +#endif + + /* + CDDA Autopause + + Silhouette Mirage ($3) + Tomb Raider 1 ($7) + */ + + if( cdr.CurTrack < btoi( subq->TrackNumber ) ) { +#ifdef CDR_LOG + CDR_LOG( "CDDA STOP\n" ); +#endif + + // Magic the Gathering + // - looping territory cdda + + // ...? + //cdr.ResultReady = 1; + //cdr.Stat = DataReady; + cdr.Stat = DataEnd; + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + + + StopCdda(); + } + } else { +#ifdef CDR_LOG___0 + CDR_LOG( "CDDA FAKE SUB - %d:%d:%d\n", + temp_cur[0], temp_cur[1], temp_cur[2] ); +#endif + + //if( msf2sec(temp_cur) >= msf2sec( temp_next ) ) { + if( fake_subq_change ) { +#ifdef CDR_LOG + CDR_LOG( "CDDA STOP\n" ); +#endif + + // Magic the Gathering + // - looping territory cdda + + // ...? + //cdr.ResultReady = 1; + //cdr.Stat = DataReady; + cdr.Stat = DataEnd; + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + + + StopCdda(); + + fake_subq_change = 0; + } + } +} + + +void cdrPlayInterrupt_Repplay() +{ + // BIOS - HACK: Switch between local / absolute times + static u8 report_time = 1; + + + if ((cdr.Mode & (MODE_REPORT|MODE_CDDA)) != (MODE_REPORT|MODE_CDDA)) return; + +#ifdef CDR_LOG + CDR_LOG("cdrRepplayInterrupt() Log: KEY END\n"); +#endif + + // Doom - no more cdda playing + // - fixes boot with irq cmd reschedule + + // Reschedule IRQ + if ( cdr.Irq || cdr.Stat ) { +#ifdef CDR_LOG + CDR_LOG("=== BUSY === cdrRepplayInterrupt\n"); +#endif + + //CDREPPLAY_INT( 0x800 ); + return; + } + + + memset( cdr.Result, 0, 8 ); + if( CDR_getStatus(&stat) == -1) return; + + cdr.Result[0] = cdr.StatP; + + + subq = (struct SubQ *)CDR_getBufferSub(); + if (subq != NULL ) { +#ifdef CDR_LOG + CDR_LOG( "REPPLAY SUB - %X:%X:%X\n", + subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] ); +#endif + + + /* + skip subQ integrity check (audio playback) + - mainly useful for DATA LibCrypt checking + */ + //if( SWAP16(subq->CRC) != calcCrc((unsigned char *)subq + 12, 10) ) + + // Rayman: audio pregap flag / track change + // - not all CDs will use PREGAPs, so we track it manually + if( cdr.CurTrack < btoi( subq->TrackNumber ) ) { + cdr.Result[0] |= 0x10; + + cdr.CurTrack = btoi( subq->TrackNumber ); + } + + + // BIOS CD Player: data already BCD format + cdr.Result[1] = subq->TrackNumber; + cdr.Result[2] = subq->IndexNumber; + + + // BIOS CD Player: switch between local / absolute times + if( report_time == 0 ) { + cdr.Result[3] = subq->AbsoluteAddress[0]; + cdr.Result[4] = subq->AbsoluteAddress[1]; + cdr.Result[5] = subq->AbsoluteAddress[2]; + + report_time = 1; + } else { + cdr.Result[3] = subq->TrackRelativeAddress[0]; + cdr.Result[4] = subq->TrackRelativeAddress[1]; + cdr.Result[5] = subq->TrackRelativeAddress[2]; + + cdr.Result[4] |= 0x80; + + report_time = 0; + } + } else { +#ifdef CDR_LOG___0 + CDR_LOG( "REPPLAY FAKE - %d:%d:%d\n", + temp_cur[0], temp_cur[1], temp_cur[2] ); +#endif + + // Rayman: check track change + //if( msf2sec(temp_cur) >= msf2sec( temp_next ) ) { + if( fake_subq_change ) { +#ifdef CDR_LOG___0 + CDR_LOG( "TRACK CHANGE %d - %d %d %d ==> %d %d %d\n", + cdr.CurTrack, + temp_cur[0], temp_cur[1], temp_cur[2], + temp_next[0], temp_next[1], temp_next[2] ); +#endif + + cdr.Result[0] |= 0x10; + + fake_subq_change = 0; + } + + + // track # / index # + cdr.Result[1] = itob(cdr.CurTrack); + cdr.Result[2] = itob(fake_subq_index); + + if( report_time == 0 ) { + // absolute + cdr.Result[3] = itob( fake_subq_real[0] ); + cdr.Result[4] = itob( fake_subq_real[1] ); + cdr.Result[5] = itob( fake_subq_real[2] ); + + report_time = 1; + } else { + // local + cdr.Result[3] = itob( fake_subq_local[0] ); + cdr.Result[4] = itob( fake_subq_local[1] ); + cdr.Result[5] = itob( fake_subq_local[2] ); + + cdr.Result[4] |= 0x80; + + report_time = 0; + } + + cdr.Result[6] = 0; + cdr.Result[7] = 0; + } + + + // Rayman: Logo freeze (resultready + dataready) + cdr.ResultReady = 1; + cdr.Stat = DataReady; + + SetResultSize(8); + psxHu32ref(0x1070) |= SWAP32((u32)0x4); +} + + +void cdrPlayInterrupt() +{ + if( !cdr.Play ) return; + + ////////////////////////////////////////// + ////////////////////////////////////////// + +#ifdef CDR_LOG + CDR_LOG( "CDDA - %d:%d:%d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] ); +#endif + + + { + u8 temp[3]; + + temp[0] = itob(cdr.SetSectorPlay[0]); + temp[1] = itob(cdr.SetSectorPlay[1]); + temp[2] = itob(cdr.SetSectorPlay[2]); + + // get subq + CDR_readTrack( temp ); + } + + if( CDR_readCDDA ) { + CDR_readCDDA( cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], cdr.Transfer ); + + CDXA_Attenuation( (short *) cdr.Transfer, 2352, 1, CDDA_ATTENUATE ); + } + + + + // mute data track + if( (Config.Cdda) || + (CDR_getStatus(&stat) != -1 && stat.Type == 1 && cdr.CurTrack == 1) ) + memset( cdr.Transfer, 0, CD_FRAMESIZE_RAW ); + + + if( SPU_playCDDAchannel) + SPU_playCDDAchannel((short *)cdr.Transfer, CD_FRAMESIZE_RAW); + + CDRPLAY_INT( cdReadTime ); + + ////////////////////////////////////////// + ////////////////////////////////////////// + + subq = (struct SubQ *)CDR_getBufferSub(); + if (subq == NULL ) + Create_Fake_Subq(); + + cdrPlayInterrupt_Autopause(); + cdrPlayInterrupt_Repplay(); + + ////////////////////////////////////////// + ////////////////////////////////////////// + + cdr.SetSectorPlay[2]++; + if (cdr.SetSectorPlay[2] == 75) { + cdr.SetSectorPlay[2] = 0; + cdr.SetSectorPlay[1]++; + if (cdr.SetSectorPlay[1] == 60) { + cdr.SetSectorPlay[1] = 0; + cdr.SetSectorPlay[0]++; + } + } + + + Check_Shell(0); +} + + +void cdrInterrupt() { + int i; + unsigned char Irq = cdr.Irq; + + // Reschedule IRQ + if (cdr.Stat) { + CDR_INT( 0x100 ); + return; + } + + cdr.Irq = 0xff; + cdr.Ctrl &= ~0x80; + + switch (Irq) { + case CdlSync: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlNop: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + if (cdr.LidCheck == 0) cdr.LidCheck = 0x20; + break; + + case CdlSetloc: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlPlay: + fake_subq_change = 0; + + if( cdr.Seeked == FALSE ) { + memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 ); + cdr.Seeked = TRUE; + } + + /* + Rayman: detect track changes + - fixes logo freeze + + Twisted Metal 2: skip PREGAP + starting accurate SubQ + - plays tracks without retry play + + Wild 9: skip PREGAP + starting accurate SubQ + - plays tracks without retry play + */ + Set_Track(); + Find_CurTrack(); + ReadTrack( cdr.SetSectorPlay ); + + // Chronicles of the Sword - getlocp timing + Create_Fake_Subq(); + + // GameShark CD Player: Calls 2x + Play 2x + if( cdr.FastBackward || cdr.FastForward ) { + if( cdr.FastForward ) cdr.FastForward--; + if( cdr.FastBackward ) cdr.FastBackward--; + + if( cdr.FastBackward == 0 && cdr.FastForward == 0 ) { + if( cdr.Play && CDR_getStatus(&stat) != -1 ) { + cdr.SetSectorPlay[0] = stat.Time[0]; + cdr.SetSectorPlay[1] = stat.Time[1]; + cdr.SetSectorPlay[2] = stat.Time[2]; + } + } + } + + + if (!Config.Cdda) { + // BIOS CD Player + // - Pause player, hit Track 01/02/../xx (Setloc issued!!) + + // GameShark CD Player: Resume play + if( cdr.ParamC == 0 ) { +#ifdef CDR_LOG___0 + CDR_LOG( "PLAY Resume @ %d:%d:%d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] ); +#endif + + //CDR_play( cdr.SetSectorPlay ); + } + else + { + // BIOS CD Player: Resume play + if( cdr.Param[0] == 0 ) { +#ifdef CDR_LOG___0 + CDR_LOG( "PLAY Resume T0 @ %d:%d:%d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] ); +#endif + + //CDR_play( cdr.SetSectorPlay ); + } + else { +#ifdef CDR_LOG___0 + CDR_LOG( "PLAY Resume Td @ %d:%d:%d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] ); +#endif + + // BIOS CD Player: Allow track replaying + StopCdda(); + + + cdr.CurTrack = btoi( cdr.Param[0] ); + + if (CDR_getTN(cdr.ResultTN) != -1) { + // check last track + if (cdr.CurTrack > cdr.ResultTN[1]) + cdr.CurTrack = cdr.ResultTN[1]; + + if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) { + cdr.SetSectorPlay[0] = cdr.ResultTD[2]; + cdr.SetSectorPlay[1] = cdr.ResultTD[1]; + cdr.SetSectorPlay[2] = cdr.ResultTD[0]; + + // reset data + Set_Track(); + Find_CurTrack(); + ReadTrack( cdr.SetSectorPlay ); + + //CDR_play(cdr.SetSectorPlay); + } + } + } + } + } + + + // Vib Ribbon: gameplay checks flag + cdr.StatP &= ~STATUS_SEEK; + + + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + cdr.StatP |= STATUS_PLAY; + + + // BIOS player - set flag again + cdr.Play = TRUE; + + CDRPLAY_INT( cdReadTime ); + break; + + case CdlForward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + + + // GameShark CD Player: Calls 2x + Play 2x + if( cdr.FastForward == 0 ) cdr.FastForward = 2; + else cdr.FastForward++; + + cdr.FastBackward = 0; + break; + + case CdlBackward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + + + // GameShark CD Player: Calls 2x + Play 2x + if( cdr.FastBackward == 0 ) cdr.FastBackward = 2; + else cdr.FastBackward++; + + cdr.FastForward = 0; + break; + + case CdlStandby: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStop: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP &= ~STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; +// cdr.Stat = Acknowledge; + + if (cdr.LidCheck == 0) cdr.LidCheck = 0x20; + break; + + case CdlPause: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + /* + Gundam Battle Assault 2: much slower (*) + - Fixes boot, gameplay + + Hokuto no Ken 2: slower + - Fixes intro + subtitles + + InuYasha - Feudal Fairy Tale: slower + - Fixes battles + */ + AddIrqQueue(CdlPause + 0x20, cdReadTime * 3); + cdr.Ctrl |= 0x80; + break; + + case CdlPause + 0x20: + SetResultSize(1); + cdr.StatP &= ~STATUS_READ; + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlInit: + SetResultSize(1); + cdr.StatP = STATUS_ROTATING; + 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 |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlDemute: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetfilter: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetmode: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlGetmode: + SetResultSize(6); + cdr.StatP |= STATUS_ROTATING; + 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] = cdr.Transfer[i]; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocP: + // GameShark CDX CD Player: uses 17 bytes output (wraps around) + SetResultSize(17); + memset( cdr.Result, 0, 16 ); + + 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); + + + // subQ integrity check - data only (skip audio) + if( subq->TrackNumber == 1 && stat.Type == 0x01 ) { + if (calcCrc((u8 *)subq + 12, 10) != (((u16)subq->CRC[0] << 8) | subq->CRC[1])) { + memset(cdr.Result + 2, 0, 3 + 3); // CRC wrong, wipe out time data + } + } + } else { + if( cdr.Play == FALSE ) Create_Fake_Subq(); + + + // track # / index # + cdr.Result[0] = itob(cdr.CurTrack); + cdr.Result[1] = itob(fake_subq_index); + + // local + cdr.Result[2] = itob( fake_subq_local[0] ); + cdr.Result[3] = itob( fake_subq_local[1] ); + cdr.Result[4] = itob( fake_subq_local[2] ); + + // absolute + cdr.Result[5] = itob( fake_subq_real[0] ); + cdr.Result[6] = itob( fake_subq_real[1] ); + cdr.Result[7] = itob( fake_subq_real[2] ); + } + + // redump.org - wipe time + if( !cdr.Play && CheckSBI(cdr.Result+5) ) { + memset( cdr.Result+2, 0, 6 ); + } + + cdr.Stat = Acknowledge; + break; + + case CdlGetTN: + // 5-Star Racing: don't stop CDDA + // + // Vib Ribbon: CD swap + StopReading(); + + cdr.CmdProcess = 0; + SetResultSize(3); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + if (CDR_getTN(cdr.ResultTN) == -1) { + cdr.Stat = DiskError; + cdr.Result[0] |= STATUS_ERROR; + } else { + cdr.Stat = Acknowledge; + cdr.Result[1] = itob(cdr.ResultTN[0]); + cdr.Result[2] = itob(cdr.ResultTN[1]); + } + break; + + case CdlGetTD: + cdr.CmdProcess = 0; + cdr.Track = btoi(cdr.Param[0]); + SetResultSize(4); + cdr.StatP |= STATUS_ROTATING; + if (CDR_getTD(cdr.Track, cdr.ResultTD) == -1) { + cdr.Stat = DiskError; + cdr.Result[0] |= STATUS_ERROR; + } else { + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = itob(cdr.ResultTD[2]); + cdr.Result[2] = itob(cdr.ResultTD[1]); + cdr.Result[3] = itob(cdr.ResultTD[0]); + } + break; + + case CdlSeekL: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.StatP |= STATUS_SEEK; + cdr.Stat = Acknowledge; + + /* + Crusaders of Might and Magic = 0.5x-4x + - fix cutscene speech start + + Eggs of Steel = 2x-? + - fix new game + + Medievil = ?-4x + - fix cutscene speech + + Rockman X5 = 0.5-4x + - fix capcom logo + */ + AddIrqQueue(CdlSeekL + 0x20, cdReadTime * 4); + break; + + case CdlSeekL + 0x20: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.StatP &= ~STATUS_SEEK; + cdr.Result[0] = cdr.StatP; + cdr.Seeked = TRUE; + cdr.Stat = Complete; + + + // Mega Man Legends 2: must update read cursor for getlocp + ReadTrack( cdr.SetSector ); + break; + + case CdlSeekP: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.StatP |= STATUS_SEEK; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekP + 0x20, cdReadTime * 1); + break; + + case CdlSeekP + 0x20: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.StatP &= ~STATUS_SEEK; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + cdr.Seeked = TRUE; + + // GameShark Music Player + memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 ); + + // Tomb Raider 2: must update read cursor for getlocp + Find_CurTrack(); + ReadTrack( cdr.SetSectorPlay ); + 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 |= STATUS_ROTATING; + 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] = 0x80; // 0x80 leads to the menu in the bios, else loads CD + } + else { + if (stat.Type == 2) { + // Music CD + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x10; + + cdr.Result[1] |= 0x80; + } + else { + // Data CD + if (CdromId[0] == '\0') { + cdr.Result[0] = 0x00; + cdr.Result[1] = 0x80; + } + else { + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x00; + } + } + } + + 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 = STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlReadT: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadT + 0x20, 0x800); + break; + + case CdlReadT + 0x20: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlReadToc: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadToc + 0x20, 0x800); + break; + + case CdlReadToc + 0x20: + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + 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, 0x800); + break; + + case READ_ACK: + if (!cdr.Reading) return; + + + // Fighting Force 2 - update subq time immediately + // - fixes new game + ReadTrack( cdr.SetSector ); + + + // Crusaders of Might and Magic - update getlocl now + // - fixes cutscene speech + { + u8 *buf = CDR_getBuffer(); + memcpy(cdr.Transfer, buf, 8); + } + + + /* + Duke Nukem: Land of the Babes - seek then delay read for one frame + - fixes cutscenes + */ + + if (!cdr.Seeked) { + cdr.Seeked = TRUE; + + cdr.StatP |= STATUS_SEEK; + cdr.StatP &= ~STATUS_READ; + + // Crusaders of Might and Magic - use short time + // - fix cutscene speech (startup) + + // ??? - use more accurate seek time later + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); + } else { + cdr.StatP |= STATUS_READ; + cdr.StatP &= ~STATUS_SEEK; + + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); + } + + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case 0xff: + return; + + default: + cdr.Stat = Complete; + break; + } + + Check_Shell( Irq ); + + if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) { + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + } + +#ifdef CDR_LOG + CDR_LOG("cdrInterrupt() Log: CDR Interrupt IRQ %x\n", Irq); +#endif +} + +void cdrReadInterrupt() { + u8 *buf; + + if (!cdr.Reading) + return; + + if (cdr.Irq || cdr.Stat) { + CDREAD_INT(0x100); + return; + } + +#ifdef CDR_LOG + CDR_LOG("cdrReadInterrupt() Log: KEY END"); +#endif + + cdr.OCUP = 1; + SetResultSize(1); + cdr.StatP |= STATUS_READ|STATUS_ROTATING; + cdr.StatP &= ~STATUS_SEEK; + cdr.Result[0] = cdr.StatP; + + ReadTrack( cdr.SetSector ); + + buf = CDR_getBuffer(); + if (buf == NULL) + cdr.RErr = -1; + + if (cdr.RErr == -1) { +#ifdef CDR_LOG + fprintf(emuLog, "cdrReadInterrupt() Log: err\n"); +#endif + memset(cdr.Transfer, 0, DATA_SIZE); + cdr.Stat = DiskError; + cdr.Result[0] |= STATUS_ERROR; + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + return; + } + + memcpy(cdr.Transfer, buf, DATA_SIZE); + CheckPPFCache(cdr.Transfer, cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); + + +#ifdef CDR_LOG + fprintf(emuLog, "cdrReadInterrupt() Log: cdr.Transfer %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); +#endif + + if ((!cdr.Muted) && (cdr.Mode & MODE_STRSND) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA + // Firemen 2: Multi-XA files - briefings, cutscenes + if( cdr.FirstSector == 1 && (cdr.Mode & MODE_SF)==0 ) { + cdr.File = cdr.Transfer[4 + 0]; + cdr.Channel = cdr.Transfer[4 + 1]; + } + + if((cdr.Transfer[4 + 2] & 0x4) && + (cdr.Transfer[4 + 1] == cdr.Channel) && + (cdr.Transfer[4 + 0] == cdr.File)) { + int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); + + if (!ret) { +#if 0 + int xa_type; + + // save - set only for FirstSector + xa_type = cdr.Xa.stereo; + + + // Duke Nukem - Time to Kill - speech, music volume control + // Tekken 3 - post-match fade out + if( cdr.Xa.stereo == 0 ) + CDXA_Attenuation( cdr.Xa.pcm, cdr.Xa.nsamples * 2, cdr.Xa.stereo, XA_ATTENUATE ); + else + CDXA_Attenuation( cdr.Xa.pcm, cdr.Xa.nsamples * 4, cdr.Xa.stereo, XA_ATTENUATE ); + + + // fix mono xa attenuation + if( cdr.Xa.stereo == 0 ) cdr.Xa.stereo = 1; +#endif + + SPU_playADPCMchannel(&cdr.Xa); + cdr.FirstSector = 0; + + +#if 0 + cdr.Xa.stereo = xa_type; +#endif + + +#if 0 + // Crash Team Racing: music, speech + // - done using cdda decoded buffer (spu irq) + // - don't do here + + // signal ADPCM data ready + psxHu32ref(0x1070) |= SWAP32((u32)0x200); +#endif + } + 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; + + // G-Police: Don't autopause ADPCM even if mode set (music) + if ((cdr.Transfer[4 + 2] & 0x80) && (cdr.Mode & MODE_AUTOPAUSE) && + (cdr.Transfer[4 + 2] & 0x4) != 0x4 ) { // EOF +#ifdef CDR_LOG + CDR_LOG("cdrReadInterrupt() Log: Autopausing read\n"); +#endif +// AddIrqQueue(AUTOPAUSE, 0x2000); + AddIrqQueue(CdlPause, 0x2000); + } + else { + CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime); + } + + /* + Croc 2: $40 - only FORM1 (*) + Judge Dredd: $C8 - only FORM1 (*) + Sim Theme Park - no adpcm at all (zero) + */ + + if( (cdr.Mode & MODE_STRSND) == 0 || (cdr.Transfer[4+2] & 0x4) != 0x4 ) { + cdr.Stat = DataReady; + } else { + // Breath of Fire 3 - fix inn sleeping + // Rockman X5 - no music restart problem + cdr.Stat = NoIntr; + } + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + + Check_Shell(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 +*/ + +unsigned char 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("cdrRead0() 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(unsigned char rt) { +#ifdef CDR_LOG + CDR_LOG("cdrWrite0() 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; + } + + // Tekken: CDXA fade-out + else if( rt == 2 ) { + //cdr.AttenuatorLeft[0] = 0; + //cdr.AttenuatorLeft[1] = 0; + } + else if( rt == 3 ) { + // Tekken 3 - character menu (don't do this!) + //cdr.AttenuatorRight[0] = 0; + //cdr.AttenuatorRight[1] = 0; + } +} + +unsigned char cdrRead1(void) { + if (cdr.ResultReady) { // && cdr.Ctrl & 0x1) { + // GameShark CDX CD Player: uses 17 bytes output (wraps around) + psxHu8(0x1801) = cdr.Result[cdr.ResultP & 0xf]; + cdr.ResultP++; + if (cdr.ResultP == cdr.ResultC) + cdr.ResultReady = 0; + } else { + psxHu8(0x1801) = 0; + } +#ifdef CDR_LOG + CDR_LOG("cdrRead1() Log: CD1 Read: %x\n", psxHu8(0x1801)); +#endif + return psxHu8(0x1801); +} + +void cdrWrite1(unsigned char rt) { + int i; + +#ifdef CDR_LOG + CDR_LOG("cdrWrite1() Log: CD1 write: %x (%s)\n", rt, CmdName[rt]); +#endif + + + // Tekken: CDXA fade-out + if( (cdr.Ctrl & 3) == 3 ) { + cdr.AttenuatorRight[0] = rt; + } + + + // psxHu8(0x1801) = rt; + cdr.Cmd = rt; + cdr.OCUP = 0; + +#ifdef CDRCMD_DEBUG + SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]); + if (cdr.ParamC) { + SysPrintf(" Param[%d] = {", cdr.ParamC); + for (i = 0; i < cdr.ParamC; i++) + SysPrintf(" %x,", cdr.Param[i]); + SysPrintf("}\n"); + } else { + SysPrintf("\n"); + } +#endif + + if (cdr.Ctrl & 0x1) return; + + switch (cdr.Cmd) { + case CdlSync: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlNop: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + + // Twisted Metal 3 - fix music + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetloc: + StopReading(); + cdr.Seeked = FALSE; + for (i = 0; i < 3; i++) + cdr.SetSector[i] = btoi(cdr.Param[i]); + cdr.SetSector[3] = 0; + +#ifdef DVD5_HACK + // PS1 DVD5 hack (shalma's disc combining kits) + dvd5_mode = cdr.Param[2] & 0x80; + + if( CDR__setDVD5 ) { + if( cdr.Param[2] & 0x80 ) + CDR__setDVD5(1); + else if( cdr.Param[1] & 0x80 ) + CDR__setDVD5(2); + else + CDR__setDVD5(0); + } + + cdr.Param[1] &= 0x7f; + cdr.Param[2] &= 0x7f; +#endif + + /* + if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) { + *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek; + }*/ + + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPlay: + // Vib Ribbon: try same track again + StopCdda(); + + // Vib Ribbon - decoded buffer IRQ for CDDA reading + // - fixes ribbon timing + music CD mode + CDRDBUF_INT( PSXCLK / 44100 * 0x100 ); + + + cdr.Play = TRUE; + + cdr.StatP |= STATUS_SEEK; + cdr.StatP &= ~STATUS_ROTATING; + + 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, 0x800); + break; + + case CdlStandby: + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlStop: + // GameShark CD Player: Reset CDDA to track start + if( cdr.Play && CDR_getStatus(&stat) != -1 ) { + cdr.SetSectorPlay[0] = stat.Time[0]; + cdr.SetSectorPlay[1] = stat.Time[1]; + cdr.SetSectorPlay[2] = stat.Time[2]; + + Find_CurTrack(); + + + // grab time for current track + CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD); + + cdr.SetSectorPlay[0] = cdr.ResultTD[2]; + cdr.SetSectorPlay[1] = cdr.ResultTD[1]; + cdr.SetSectorPlay[2] = cdr.ResultTD[0]; + } + + StopCdda(); + StopReading(); + + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPause: + /* + GameShark CD Player: save time for resume + + Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors + */ + + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReset: + case CdlInit: + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlMute: + cdr.Muted = TRUE; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + + // Duke Nukem - Time to Kill + // - do not directly set cd-xa volume + //SPU_writeRegister( H_CDLeft, 0x0000 ); + //SPU_writeRegister( H_CDRight, 0x0000 ); + break; + + case CdlDemute: + cdr.Muted = FALSE; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + + // Duke Nukem - Time to Kill + // - do not directly set cd-xa volume + //SPU_writeRegister( H_CDLeft, 0x7f00 ); + //SPU_writeRegister( H_CDRight, 0x7f00 ); + 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("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]); +#endif + cdr.Mode = cdr.Param[0]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + + // Squaresoft on PlayStation 1998 Collector's CD Vol. 1 + // - fixes choppy movie sound + if( cdr.Play && (cdr.Mode & MODE_CDDA) == 0 ) + StopCdda(); + break; + + case CdlGetmode: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocL: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + + // Crusaders of Might and Magic - cutscene speech + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocP: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + + // GameShark CDX / Lite Player: pretty narrow time window + // - doesn't always work due to time inprecision + //AddIrqQueue(cdr.Cmd, 0x28); + + // Tomb Raider 2 - cdda + AddIrqQueue(cdr.Cmd, 0x40); + break; + + case CdlGetTN: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + //AddIrqQueue(cdr.Cmd, 0x800); + + // GameShark CDX CD Player: very long time + AddIrqQueue(cdr.Cmd, 0x100000); + break; + + case CdlGetTD: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekL: +// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + + StopCdda(); + StopReading(); + + break; + + case CdlSeekP: +// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + + // Tomb Raider 2 - reset cdda + StopCdda(); + StopReading(); + + AddIrqQueue(cdr.Cmd, 0x800); + break; + + // Destruction Derby: read TOC? GetTD after this + case CdlReadT: + 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, 0x800); + break; + + case CdlReadToc: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + default: +#ifdef CDR_LOG + CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd); +#endif + return; + } + if (cdr.Stat != NoIntr) { + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + } +} + +unsigned char cdrRead2(void) { + unsigned char ret; + + if (cdr.Readed == 0) { + ret = 0; + } else { + ret = cdr.Transfer[cdr.transferIndex]; + cdr.transferIndex++; + adjustTransferIndex(); + } + +#ifdef CDR_LOG + CDR_LOG("cdrRead2() Log: CD2 Read: %x\n", ret); +#endif + return ret; +} + +void cdrWrite2(unsigned char rt) { +#ifdef CDR_LOG + CDR_LOG("cdrWrite2() Log: CD2 write: %x\n", rt); +#endif + + + // Tekken: CDXA fade-out + if( (cdr.Ctrl & 3) == 2 ) { + cdr.AttenuatorLeft[0] = rt; + } + else if( (cdr.Ctrl & 3) == 3 ) { + cdr.AttenuatorRight[1] = rt; + } + + + + if (cdr.Ctrl & 0x1) { + switch (rt) { + case 0x07: + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 1; //0; + cdr.Ctrl &= ~3; //cdr.Ctrl = 0; + break; + + default: + cdr.Reg2 = rt; + break; + } + } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) { + cdr.Param[cdr.ParamP++] = rt; + cdr.ParamC++; + } +} + +unsigned char 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("cdrRead3() Log: CD3 Read: %x\n", psxHu8(0x1803)); +#endif + return psxHu8(0x1803); +} + +void cdrWrite3(unsigned char rt) { +#ifdef CDR_LOG + CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt); +#endif + + // Tekken: CDXA fade-out + if( (cdr.Ctrl & 3) == 2 ) { + cdr.AttenuatorLeft[1] = rt; + } + else if( (cdr.Ctrl & 3) == 3 && rt == 0x20 ) { +#ifdef CDR_LOG + CDR_LOG( "CD-XA Volume: %X %X | %X %X\n", + cdr.AttenuatorLeft[0], cdr.AttenuatorLeft[1], + cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] ); +#endif + } + + + // GameShark CDX CD Player: Irq timing mania + if( rt == 0 && + cdr.Irq != 0 && cdr.Irq != 0xff && + cdr.ResultReady == 0 ) { + + // GS CDX: ~0x28 cycle timing - way too precise + if( cdr.Irq == CdlGetlocP ) { + cdrInterrupt(); + + psxRegs.interrupt &= ~(1 << PSXINT_CDR); + } + } + + + if (rt == 0x07 && cdr.Ctrl & 0x1) { + cdr.Stat = 0; + + if (cdr.Irq == 0xff) { + cdr.Irq = 0; + return; + } + +#if 0 + if (cdr.Reading && !cdr.ResultReady) { + CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime); + } +#else + // XA streaming - incorrect timing because of this reschedule + // - Final Fantasy Tactics + // - various other games + + /* + if (cdr.Reading && !cdr.ResultReady) { + CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime); + } + */ +#endif + + return; + } + + if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { + cdr.Readed = 1; + cdr.transferIndex = 0; + + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { + case MODE_SIZE_2328: + case MODE_SIZE_2048: + cdr.transferIndex += 12; + break; + + case MODE_SIZE_2340: + cdr.transferIndex += 0; + break; + + default: + break; + } + } +} + +void psxDma3(u32 madr, u32 bcr, u32 chcr) { + u32 cdsize; + u8 *ptr/*, *cdwrap_ptr*/; + +#ifdef CDR_LOG + CDR_LOG("psxDma3() Log: *** DMA 3 *** %x addr = %x size = %x\n", chcr, madr, bcr); +#endif + + switch (chcr) { + case 0x11000000: + case 0x11400100: + if (cdr.Readed == 0) { +#ifdef CDR_LOG + CDR_LOG("psxDma3() Log: *** DMA 3 *** NOT READY\n"); +#endif + break; + } + + cdsize = (bcr & 0xffff) * 4; + + // Ape Escape: bcr = 0001 / 0000 + // - fix boot + if( cdsize == 0 ) + { + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { + case MODE_SIZE_2340: cdsize = 2340; break; + case MODE_SIZE_2328: cdsize = 2328; break; + case MODE_SIZE_2048: cdsize = 2048; break; + } + } + + + ptr = (u8 *)PSXM(madr); + if (ptr == NULL) { +#ifdef CPU_LOG + CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n"); +#endif + break; + } + +/* +#if 1 + + // GS CDX: Enhancement CD crash + // - Setloc 0:0:0 + // - CdlPlay + // - Spams DMA3 and gets buffer overrun + + if( (cdr.pTransfer-cdr.Transfer) + cdsize > 2352 ) + { + // avoid crash - probably should wrap here + //memcpy(ptr, cdr.pTransfer, cdsize); + } + else + { + memcpy(ptr, cdr.pTransfer, cdsize); + } + + psxCpu->Clear(madr, cdsize / 4); + cdr.pTransfer += cdsize; +#else + cdwrap_ptr = cdr.Transfer; + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { + case MODE_SIZE_2340: cdwrap_ptr += 2340; break; + case MODE_SIZE_2328: cdwrap_ptr += 12 + 2328; break; + case MODE_SIZE_2048: cdwrap_ptr += 12 + 2048; break; + } + + + // fast copy - no wrap + if( cdr.pTransfer + cdsize <= cdwrap_ptr ) { + memcpy(ptr, cdr.pTransfer, cdsize); + + psxCpu->Clear(madr, cdsize / 4); + cdr.pTransfer += cdsize; + } else { + int lcv; + + // CDROM wrapping + // + // Ape Escape - used several times + // Gameshark Lite - opening movie + // + // Gameshark CDX: enhancement CD patcher + // - calls CdlPlay @ 0:2:0 + // - spams DMA3 and overruns buffer + + for( lcv = 0; lcv < cdsize; lcv++ ) + { + // wrap cdrom ptr + if( cdr.pTransfer == cdwrap_ptr ) { + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { + case MODE_SIZE_2328: + case MODE_SIZE_2048: + cdr.pTransfer = cdr.Transfer + 12; + break; + + case MODE_SIZE_2340: + cdr.pTransfer = cdr.Transfer + 0; + break; + } + } + + + *(ptr+lcv) = *cdr.pTransfer; + + cdr.pTransfer++; + } + + psxCpu->Clear(madr, cdsize / 4); + } +#endif +*/ + { + int i; + + for(i = 0; i < cdsize; ++i) { + ptr[i] = cdr.Transfer[cdr.transferIndex]; + cdr.transferIndex++; + adjustTransferIndex(); + } + + psxCpu->Clear(madr, cdsize / 4); + } + + // burst vs normal + if( chcr == 0x11400100 ) { +#if 1 + CDRDMA_INT( (cdsize/4) / 4 ); +#else + // Experimental burst dma transfer (0.333x max) + CDRDMA_INT( (cdsize/4) / 3 ); +#endif + } + else if( chcr == 0x11000000 ) { + CDRDMA_INT( (cdsize/4) * 1 ); + } + return; + + default: +#ifdef CDR_LOG + CDR_LOG("psxDma3() Log: Unknown cddma %x\n", chcr); +#endif + break; + } + + HW_DMA3_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(3); +} + +void cdrDmaInterrupt() +{ + HW_DMA3_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(3); +} + +void cdrReset() { + memset(&cdr, 0, sizeof(cdr)); + cdr.CurTrack = 1; + cdr.File = 1; + cdr.Channel = 1; + +#if 0 + // BIOS player - default values + cdr.AttenuatorLeft[0] = 0x80; + cdr.AttenuatorLeft[1] = 0x00; + cdr.AttenuatorRight[0] = 0x80; + cdr.AttenuatorRight[1] = 0x00; +#endif +} + +int cdrFreeze(gzFile f, int Mode) { + unsigned int tmp; + + + if( Mode == 0 ) { + StopCdda(); + } + + + gzfreeze(&cdr, sizeof(cdr)); + + + + if (Mode == 1) + tmp = cdr.transferIndex; + + gzfreeze(&tmp, sizeof(tmp)); + + if (Mode == 0) + cdr.transferIndex = tmp; + + return 0; +} + +void LidInterrupt() { + cdr.LidCheck = 0x20; // start checker + + CDRLID_INT( cdReadTime * 3 ); + + // generate interrupt if none active - open or close + if (cdr.Irq == 0 || cdr.Irq == 0xff) { + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(CdlNop, 0x800); + } +} diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h index 512c3216..943564e2 100644..100755 --- a/libpcsxcore/cdrom.h +++ b/libpcsxcore/cdrom.h @@ -1,121 +1,121 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#ifndef __CDROM_H__
-#define __CDROM_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "psxcommon.h"
-#include "decode_xa.h"
-#include "r3000a.h"
-#include "plugins.h"
-#include "psxmem.h"
-#include "psxhw.h"
-
-#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 MSF2SECT(m, s, f) (((m) * 60 + (s) - 2) * 75 + (f))
-
-#define CD_FRAMESIZE_RAW 2352
-#define DATA_SIZE (CD_FRAMESIZE_RAW - 12)
-
-#define SUB_FRAMESIZE 96
-
-typedef struct {
- unsigned char OCUP;
- unsigned char Reg1Mode;
- unsigned char Reg2;
- unsigned char CmdProcess;
- unsigned char Ctrl;
- unsigned char Stat;
-
- unsigned char StatP;
-
- unsigned char Transfer[CD_FRAMESIZE_RAW];
- unsigned int transferIndex;
-
- unsigned char Prev[4];
- unsigned char Param[8];
- unsigned char Result[16];
-
- unsigned char ParamC;
- unsigned char ParamP;
- unsigned char ResultC;
- unsigned char ResultP;
- unsigned char ResultReady;
- unsigned char Cmd;
- unsigned char Readed;
- u32 Reading;
-
- unsigned char ResultTN[6];
- unsigned char ResultTD[4];
- unsigned char SetSector[4];
- unsigned char SetSectorSeek[4];
- unsigned char SetSectorPlay[4];
- unsigned char Track;
- boolean Play, Muted;
- int CurTrack;
- int Mode, File, Channel;
- int Reset;
- int RErr;
- int FirstSector;
-
- xa_decode_t Xa;
-
- int Init;
-
- unsigned char Irq;
- u32 eCycle;
-
- boolean Seeked;
-
- u8 LidCheck;
- u8 FastForward;
- u8 FastBackward;
-
- u8 AttenuatorLeft[2], AttenuatorRight[2];
-} cdrStruct;
-
-extern cdrStruct cdr;
-
-void cdrDecodedBufferInterrupt();
-
-void cdrReset();
-void cdrInterrupt();
-void cdrReadInterrupt();
-void cdrLidSeekInterrupt();
-void cdrPlayInterrupt();
-unsigned char cdrRead0(void);
-unsigned char cdrRead1(void);
-unsigned char cdrRead2(void);
-unsigned char cdrRead3(void);
-void cdrWrite0(unsigned char rt);
-void cdrWrite1(unsigned char rt);
-void cdrWrite2(unsigned char rt);
-void cdrWrite3(unsigned char rt);
-int cdrFreeze(gzFile f, int Mode);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef __CDROM_H__ +#define __CDROM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psxcommon.h" +#include "decode_xa.h" +#include "r3000a.h" +#include "plugins.h" +#include "psxmem.h" +#include "psxhw.h" + +#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 MSF2SECT(m, s, f) (((m) * 60 + (s) - 2) * 75 + (f)) + +#define CD_FRAMESIZE_RAW 2352 +#define DATA_SIZE (CD_FRAMESIZE_RAW - 12) + +#define SUB_FRAMESIZE 96 + +typedef struct { + unsigned char OCUP; + unsigned char Reg1Mode; + unsigned char Reg2; + unsigned char CmdProcess; + unsigned char Ctrl; + unsigned char Stat; + + unsigned char StatP; + + unsigned char Transfer[CD_FRAMESIZE_RAW]; + unsigned int transferIndex; + + unsigned char Prev[4]; + unsigned char Param[8]; + unsigned char Result[16]; + + unsigned char ParamC; + unsigned char ParamP; + unsigned char ResultC; + unsigned char ResultP; + unsigned char ResultReady; + unsigned char Cmd; + unsigned char Readed; + u32 Reading; + + unsigned char ResultTN[6]; + unsigned char ResultTD[4]; + unsigned char SetSector[4]; + unsigned char SetSectorSeek[4]; + unsigned char SetSectorPlay[4]; + unsigned char Track; + boolean Play, Muted; + int CurTrack; + int Mode, File, Channel; + int Reset; + int RErr; + int FirstSector; + + xa_decode_t Xa; + + int Init; + + unsigned char Irq; + u32 eCycle; + + boolean Seeked; + + u8 LidCheck; + u8 FastForward; + u8 FastBackward; + + u8 AttenuatorLeft[2], AttenuatorRight[2]; +} cdrStruct; + +extern cdrStruct cdr; + +void cdrDecodedBufferInterrupt(); + +void cdrReset(); +void cdrInterrupt(); +void cdrReadInterrupt(); +void cdrLidSeekInterrupt(); +void cdrPlayInterrupt(); +unsigned char cdrRead0(void); +unsigned char cdrRead1(void); +unsigned char cdrRead2(void); +unsigned char cdrRead3(void); +void cdrWrite0(unsigned char rt); +void cdrWrite1(unsigned char rt); +void cdrWrite2(unsigned char rt); +void cdrWrite3(unsigned char rt); +int cdrFreeze(gzFile f, int Mode); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/debug.c b/libpcsxcore/debug.c index 711d96f3..fc717da6 100644..100755 --- a/libpcsxcore/debug.c +++ b/libpcsxcore/debug.c @@ -1,1145 +1,1145 @@ -/* Pcsx - Pc Psx Emulator
- * Copyright (C) 1999-2003 Pcsx 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, see <http://www.gnu.org/licenses>.
- */
-
-#include "psxcommon.h"
-#include "r3000a.h"
-#include "debug.h"
-#include "socket.h"
-
-/*
-PCSXR Debug console protocol description, version 1.0
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Commands number are formatted using %03X (yes)
-Registers number are formatted using %02X.
-Breakpoints numbers are formatted using %X
-All other values are formatted using %08X, unless specified.
-
-
-Client inputs:
-~~~~~~~~~~~~~
-Basic commands (1xx):
---------------------
-100 <message>
- Sends a dumb message. Will be replied with a 200 reply, followed by the message.
-101
- Gets PCSXR version.
-102
- Gets protocol version.
-103
- Gets status
-110
- Gets PC.
-111 [reg]
- Gets GP register, or all, if no argument.
-112
- Gets LO/HI registers.
-113 [reg]
- Gets COP0 register, or all, if no argument.
-114 [reg]
- Gets COP2 control register, or all, if no argument.
-115 [reg]
- Gets COP2 data register, or all, if no argument.
-119 [pc]
- Disassemble current PC, or given PC.
-121 <reg>=<value>
- Sets a GP register. Will return a 221 message.
-122 <LO|HI>=<value>
- Sets LO or HI register. Will return a 222 message.
-123 <reg>=<value>
- Sets a COP0 register. Will return a 223 message.
-124 <reg>=<value>
- Sets a COP2 control register. Will return a 224 message.
-125 <reg>=<value>
- Sets a COP2 data register. Will return a 225 message.
-130 <size>@<addr>
- Dumps a range of memory, of size bytes starting at addr.
-140 <size>@<addr>
- Sets a range of memory, of size bytes starting at addr.
- Will have to send immediately exactly size bytes afterward.
-150 [number]
- Starts/reset mapping execution flow, or stop it if number = 0
-151 [number]
- Starts/reset mapping read8 flow, or stop it if number = 0
-152 [number]
- Starts/reset mapping read16 flow, or stop it if number = 0
-153 [number]
- Starts/reset mapping read32 flow, or stop it if number = 0
-154 [number]
- Starts/reset mapping write8 flow, or stop it if number = 0
-155 [number]
- Starts/reset mapping write16 flow, or stop it if number = 0
-156 [number]
- Starts/reset mapping write32 flow, or stop it if number = 0
-160 [number]
- Breaks on map exec flow, or stop it if number = 0
-161 [number]
- Breaks on map read8 flow, or stop it if number = 0
-162 [number]
- Breaks on map read16 flow, or stop it if number = 0
-163 [number]
- Breaks on map read32 flow, or stop it if number = 0
-164 [number]
- Breaks on map write8 flow, or stop it if number = 0
-165 [number]
- Breaks on map write16 flow, or stop it if number = 0
-166 [number]
- Breaks on map write32 flow, or stop it if number = 0
-170
- Dumps the execution flow map in an IDC file
-
-Execution flow control commands (3xx):
--------------------------------------
-300 [number]
- Get a list of the actual breakpoints. Will get '400' answers.
-301 [number]
- Deletes a breakpoint, or all, if no arguments.
-310 <address>
- Sets an exec breakpoint.
-320 <address>
- Sets a read breakpoint, 1 byte / 8 bits.
-321 <address>
- Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address.
-322 <address>
- Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
-330 <address>
- Sets a write breakpoint, 1 byte / 8 bits.
-331 <address>
- Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address.
-332 <address>
- Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
-390
- Pauses execution. Equivalents to a breakpoint.
-391
- Restarts execution.
-395 [number]
- Traces execution, 1 instruction by default. Formatted using %i
-398
- Soft (quick) resets.
-399
- Resets.
-
-
-Server outputs:
-~~~~~~~~~~~~~~
-Spontaneous messages (0xx):
---------------------------
-000 <message>
- Greeting banner.
-010 / 011 / 012 / 013 / 014 / 015 / 016
- Execution hit mapping flow automatic breakpoint.
-030 <number>@<PC>
- Execution hit breakpoint, PCSXR is paused. Displays PC's value.
-
-Basic commands acknowledge (2xx):
---------------------------------
-200 <message>
- Sends a dumb message.
-201 <message>
- Returns PCSXR version.
-202 <message>
- Returns protocol version.
-203 <status>
- status = 0: running; = 1: paused; = 2: trace
-210 PC=<value>
- Displays current PC value.
-211 <reg>=<value>
- Displays one GP register value.
-212 LO=<value> HI=<value>
- Displays LO/HI registers.
-213 <reg>=<value>
- Displays one COP0 register value.
-214 <reg>=<value>
- Displays one COP2 control register value.
-215 <reg>=<value>
- Displays one COP2 data register value.
-219 <message>
- Displays one line of disassembled code.
-221 <reg>=<value>
- Displays one GP register value, ack for modification.
-222 LO=<value> HI=<value>
- Displays LO/HI registers, ack for modification.
-223 <reg>=<value>
- Displays one COP0 register value, ack for modification.
-224 <reg>=<value>
- Displays one COP2 control register value, ack for modification.
-225 <reg>=<value>
- Displays one COP2 data register value, ack for modification.
-230 <size>@<addr>
- Dumping memory. Will then raw outputs size bytes.
-240 <size>@<addr>
- Memory set acknowledge.
-250 / 251 / 252 / 253 / 254 / 255 / 256
- Acknolwedge of 15x commands.
-260 / 261 / 262 / 263 / 264 / 265 / 266
- Acknolwedge of 16x commands.
-270
- Acknolwedge of 170 command.
-
-Execution flow control commands acknowledge (4xx):
--------------------------------------------------
-400 <number>@<address>-<type>
- Displays a breakpoint, where 'type' can be of BE, BR1, BR2, BR4, BW1, BW2 or BW4.
-401 <message>
- Breakpoint deleting acknowledge.
-410, 420, 421, 422, 430, 431, 432 <number>
- Breakpoint adding acknowledge. Returns the number of the added breakpoint.
-490 <message>
- Pausing.
-491 <message>
- Resuming.
-495 <message>
- Tracing.
-498 <message>
- Soft resetting.
-499 <message>
- Resetting.
-
-Error messages (5xx):
---------------------
-500 <message>
- Command not understood.
-511 <message>
- Invalid GPR register.
-512 <message>
- Invalid LO/HI register.
-513, 514 <message>
- Invalid range or address.
-530 <message>
- Non existant breakpoint.
-531, 532, 533 <message>
- Invalid breakpoint address.
-*/
-
-static int debugger_active = 0, paused = 0, trace = 0, reset = 0, resetting = 0;
-static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0;
-static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0;
-
-static void ProcessCommands();
-
-static u8 *MemoryMap = NULL;
-
-enum {
- MAP_EXEC = 1,
- MAP_R8 = 2,
- MAP_R16 = 4,
- MAP_R32 = 8,
- MAP_W8 = 16,
- MAP_W16 = 32,
- MAP_W32 = 64,
- MAP_EXEC_JAL = 128,
-};
-
-char *breakpoint_type_names[] = {
- "E", "R1", "R2", "R4", "W1", "W2", "W4"
-};
-
-typedef struct breakpoint_s {
- struct breakpoint_s *next, *prev;
- int number, type;
- u32 address;
-} breakpoint_t;
-
-static breakpoint_t *first = NULL;
-
-int add_breakpoint(int type, u32 address) {
- breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t));
-
- bp->type = type;
- bp->address = address;
-
- if (first) {
- bp->number = first->prev->number + 1;
- bp->next = first;
- bp->prev = first->prev;
- first->prev = bp;
- bp->prev->next = bp;
- } else {
- first = bp;
- bp->number = 1;
- bp->next = bp;
- bp->prev = bp;
- }
-
- return bp->number;
-}
-
-void delete_breakpoint(breakpoint_t * bp) {
- if (bp == first) {
- if (bp->next == bp) {
- first = NULL;
- } else {
- first = bp->next;
- }
- }
-
- bp->next->prev = bp->prev;
- bp->prev->next = bp->next;
-
- free(bp);
-}
-
-breakpoint_t *next_breakpoint(breakpoint_t *bp) {
- return bp->next != first ? bp->next : 0;
-}
-
-breakpoint_t *find_breakpoint(int number) {
- breakpoint_t *p;
-
- for (p = first; p; p = next_breakpoint(p)) {
- if (p->number == number)
- return p;
- }
-
- return 0;
-}
-
-void StartDebugger() {
- if (debugger_active)
- return;
-
- MemoryMap = (u8 *)malloc(0x200000);
- if (MemoryMap == NULL) {
- SysMessage(_("Error allocating memory"));
- return;
- }
-
- if (StartServer() == -1) {
- SysPrintf(_("Unable to start debug server.\n"));
- return;
- }
-
- SysPrintf(_("Debugger started.\n"));
- debugger_active = 1;
-}
-
-void StopDebugger() {
- if (debugger_active) {
- StopServer();
- SysPrintf(_("Debugger stopped.\n"));
- }
-
- if (MemoryMap != NULL) {
- free(MemoryMap);
- MemoryMap = NULL;
- }
-
- while (first != NULL) delete_breakpoint(first);
-
- debugger_active = 0;
-}
-
-void PauseDebugger() {
- trace = 0;
- paused = 1;
-}
-
-void ResumeDebugger() {
- trace = 0;
- paused = 0;
-}
-
-void DebugVSync() {
- if (!debugger_active || resetting)
- return;
-
- if (reset) {
- resetting = 1;
- CheckCdrom();
- SysReset();
- if (reset == 2)
- LoadCdrom();
- reset = resetting = 0;
- return;
- }
-
- GetClient();
- ProcessCommands();
-}
-
-void MarkMap(u32 address, int mask) {
- if ((address & 0xff000000) != 0x80000000) return;
- MemoryMap[address & 0x001fffff] |= mask;
-}
-
-int IsMapMarked(u32 address, int mask) {
- return (MemoryMap[address & 0x001fffff] & mask) != 0;
-}
-
-void ProcessDebug() {
- if (!debugger_active || reset || resetting)
- return;
- if (trace) {
- if (!(--trace)) {
- paused = 1;
- }
- }
- if (!paused) {
- DebugCheckBP(psxRegs.pc, BE);
- }
- if (mapping_e) {
- MarkMap(psxRegs.pc, MAP_EXEC);
- if ((psxRegs.code >> 26) == 3) {
- MarkMap(_JumpTarget_, MAP_EXEC_JAL);
- }
- if (((psxRegs.code >> 26) == 0) && ((psxRegs.code & 0x3F) == 9)) {
- MarkMap(_Rd_, MAP_EXEC_JAL);
- }
- }
- while (paused) {
- GetClient();
- ProcessCommands();
- GPU_updateLace();
- SysUpdate();
- }
-}
-
-static void ProcessCommands() {
- int code, i, dumping;
- FILE *sfile;
- char cmd[257], *arguments, *p, reply[10240], *save, *dump;
- u32 reg, value, size, address;
- breakpoint_t *bp;
-
- if (!HasClient())
- return;
- if (ReadSocket(cmd, 256) > 0) {
- arguments = NULL;
- if (strlen(cmd) <= 2) {
- code = 0;
- } else if (strlen(cmd) == 3) {
- code = strtol(cmd, 0, 16);
- } else if (!(isxdigit(cmd[0]) && isxdigit(cmd[1]) && isxdigit(cmd[2]) && (cmd[3] == 0x20))) {
- code = 0;
- } else if (sscanf(cmd, "%3X ", &code) != 1) {
- code = 0;
- } else {
- arguments = cmd + 4;
- }
- code = strtol(cmd, &arguments, 16);
- while (arguments && *arguments && *arguments == 0x20)
- arguments++;
-
- if (*arguments == '\0')
- arguments = NULL;
-
- dumping = 0;
- save = NULL;
-
- switch (code) {
- case 0x100:
- sprintf(reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments);
- break;
- case 0x101:
- sprintf(reply, "201 %s\r\n", PACKAGE_VERSION);
- break;
- case 0x102:
- sprintf(reply, "202 1.0\r\n");
- break;
- case 0x103:
- sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0);
- break;
- case 0x110:
- sprintf(reply, "210 PC=%08X\r\n", psxRegs.pc);
- break;
- case 0x111:
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd);
- break;
- }
- }
- if (!arguments) {
- reply[0] = 0;
- for (i = 0; i < 32; i++) {
- sprintf(reply, "%s211 %02X=%08X\r\n", reply, i, psxRegs.GPR.r[i]);
- }
- } else {
- if ((code >= 0) && (code < 32)) {
- sprintf(reply, "211 %02X=%08X\r\n", code, psxRegs.GPR.r[code]);
- } else {
- sprintf(reply, "511 Invalid GPR register: %X\r\n", code);
- }
- }
- break;
- case 0x112:
- sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi);
- break;
- case 0x113:
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "511 Malformed 113 command '%s'\r\n", cmd);
- break;
- }
- }
- if (!arguments) {
- reply[0] = 0;
- for (i = 0; i < 32; i++) {
- sprintf(reply, "%s213 %02X=%08X\r\n", reply, i, psxRegs.CP0.r[i]);
- }
- } else {
- if ((code >= 0) && (code < 32)) {
- sprintf(reply, "213 %02X=%08X\r\n", code, psxRegs.CP0.r[code]);
- } else {
- sprintf(reply, "511 Invalid COP0 register: %X\r\n", code);
- }
- }
- break;
- case 0x114:
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "511 Malformed 114 command '%s'\r\n", cmd);
- break;
- }
- }
- if (!arguments) {
- reply[0] = 0;
- for (i = 0; i < 32; i++) {
- sprintf(reply, "%s214 %02X=%08X\r\n", reply, i, psxRegs.CP2C.r[i]);
- }
- } else {
- if ((code >= 0) && (code < 32)) {
- sprintf(reply, "214 %02X=%08X\r\n", code, psxRegs.CP2C.r[code]);
- } else {
- sprintf(reply, "511 Invalid COP2C register: %X\r\n", code);
- }
- }
- break;
- case 0x115:
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd);
- break;
- }
- }
- if (!arguments) {
- reply[0] = 0;
- for (i = 0; i < 32; i++) {
- sprintf(reply, "%s215 %02X=%08X\r\n", reply, i, psxRegs.CP2D.r[i]);
- }
- } else {
- if ((code >= 0) && (code < 32)) {
- sprintf(reply, "215 %02X=%08X\r\n", code, psxRegs.CP2D.r[code]);
- } else {
- sprintf(reply, "511 Invalid COP2D register: %X\r\n", code);
- }
- }
- break;
- case 0x119:
- if (arguments) {
- if (sscanf(arguments, "%08X", &code) != 1) {
- sprintf(reply, "511 Malformed 119 command '%s'\r\n", cmd);
- break;
- }
- }
- if (!arguments)
- code = psxRegs.pc;
-
- sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code));
- break;
- case 0x121:
- if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
- sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments);
- break;
- }
-
- if (reg < 32) {
- psxRegs.GPR.r[reg] = value;
- sprintf(reply, "221 %02X=%08X\r\n", reg, value);
- } else {
- sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg);
- }
- break;
- case 0x122:
- if (!arguments || strncmp(arguments, "HI=", 3) == 0) {
- reg = 33;
- } else if (arguments && strncmp(arguments, "LO=", 3) == 0) {
- reg = 32;
- } else {
- arguments[2] = 0;
- sprintf(reply, "512 Invalid LO/HI register: '%s'\r\n", arguments);
- break;
- }
-
- if (sscanf(arguments + 3, "%08X", &value) != 1) {
- sprintf(reply, "500 Malformed 122 command '%s'\r\n", arguments);
- } else {
- psxRegs.GPR.r[reg] = value;
- sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi);
- }
- break;
- case 0x123:
- if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
- sprintf(reply, "500 Malformed 123 command '%s'\r\n", arguments);
- break;
- }
-
- if (reg < 32) {
- psxRegs.CP0.r[reg] = value;
- sprintf(reply, "223 %02X=%08X\r\n", reg, value);
- } else {
- sprintf(reply, "512 Invalid COP0 register: %02X\r\n", reg);
- }
- break;
- case 0x124:
- if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
- sprintf(reply, "500 Malformed 124 command '%s'\r\n", arguments);
- break;
- }
-
- if (reg < 32) {
- psxRegs.CP2C.r[reg] = value;
- sprintf(reply, "224 %02X=%08X\r\n", reg, value);
- } else {
- sprintf(reply, "512 Invalid COP2C register: %02X\r\n", reg);
- }
- break;
- case 0x125:
- if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
- sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments);
- break;
- }
-
- if (reg < 32) {
- psxRegs.CP2D.r[reg] = value;
- sprintf(reply, "225 %02X=%08X\r\n", reg, value);
- } else {
- sprintf(reply, "512 Invalid COP2D register: %02X\r\n", reg);
- }
- break;
- case 0x130:
- if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) {
- sprintf(reply, "500 Malformed 130 command '%s'\r\n", arguments);
- break;
- }
-
- if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) {
- sprintf(reply, "230 %08X@%08X\r\n", size, address);
- dump = (char *) PSXM(address);
- dumping = 1;
- } else {
- sprintf(reply, "513 Invalid address or range: '%s'\r\n", arguments);
- }
- break;
- case 0x140:
- if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) {
- sprintf(reply, "500 Malformed 140 command '%s'\r\n", arguments);
- break;
- }
-
- if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) {
- sprintf(reply, "240 %08X@%08X\r\n", size, address);
- RawReadSocket((char *)PSXM(address), size);
- } else {
- sprintf(reply, "514 Invalid address or range: '%s'\r\n", arguments);
- }
- break;
- case 0x150:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 150 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_e = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_EXEC;
- MemoryMap[i] &= ~MAP_EXEC_JAL;
- }
- } else {
- mapping_e = 0;
- }
- sprintf(reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x151:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 151 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_r8 = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_R8;
- }
- } else {
- mapping_r8 = 0;
- }
- sprintf(reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x152:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 152 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_r16 = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_R16;
- }
- } else {
- mapping_r16 = 0;
- }
- sprintf(reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x153:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 153 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_r32 = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_R32;
- }
- } else {
- mapping_r32 = 0;
- }
- sprintf(reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x154:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 154 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_w8 = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_W8;
- }
- } else {
- mapping_w8 = 0;
- }
- sprintf(reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x155:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 155 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_w16 = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_W16;
- }
- } else {
- mapping_w16 = 0;
- }
- sprintf(reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x156:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 156 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- mapping_w32 = 1;
- for (i = 0; i < 0x00200000; i++) {
- MemoryMap[i] &= ~MAP_W32;
- }
- } else {
- mapping_w32 = 0;
- }
- sprintf(reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x160:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 160 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_e = 1;
- } else {
- breakmp_e = 0;
- }
- sprintf(reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x161:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 161 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_r8 = 1;
- } else {
- breakmp_r8 = 0;
- }
- sprintf(reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x162:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 162 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_r16 = 1;
- } else {
- breakmp_r16 = 0;
- }
- sprintf(reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x163:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 163 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_r32 = 1;
- } else {
- breakmp_r32 = 0;
- }
- sprintf(reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x164:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 164 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_w8 = 1;
- } else {
- breakmp_w8 = 0;
- }
- sprintf(reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x165:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 165 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_w16 = 1;
- } else {
- breakmp_w16 = 0;
- }
- sprintf(reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x166:
- code = 1;
- if (arguments) {
- if (sscanf(arguments, "%02X", &code) != 1) {
- sprintf(reply, "500 Malformed 166 command '%s'\r\n", cmd);
- break;
- }
- }
- if (code) {
- breakmp_w32 = 1;
- } else {
- breakmp_w32 = 0;
- }
- sprintf(reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped");
- break;
- case 0x170:
- sfile = fopen("flow.idc", "wb");
- fprintf(sfile, "#include <idc.idc>\r\n\r\n");
- fprintf(sfile, "static main(void) {\r\n");
- for (i = 0; i < 0x00200000; i++) {
- if (IsMapMarked(i, MAP_EXEC_JAL)) {
- fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i);
- }
- }
- fprintf(sfile, "}\r\n");
- fclose(sfile);
- sfile = fopen("markcode.idc", "wb");
- fprintf(sfile, "#include <idc.idc>\r\n\r\n");
- fprintf(sfile, "static main(void) {\r\n");
- for (i = 0; i < 0x00200000; i++) {
- if (IsMapMarked(i, MAP_EXEC)) {
- fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i);
- }
- }
- fprintf(sfile, "}\r\n");
- fclose(sfile);
- sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n");
- break;
- case 0x300:
- p = arguments;
- if (arguments) {
- code = strtol(arguments, &p, 16);
- }
- if (p == arguments) {
- if (first) {
- reply[0] = 0;
- for (bp = first; bp; bp = next_breakpoint(bp)) {
- sprintf(reply, "%s400 %X@%08X-%s\r\n", reply, bp->number, bp->address, breakpoint_type_names[bp->type]);
- }
- } else {
- sprintf(reply, "530 No breakpoint\r\n");
- }
- } else {
- if ((bp = find_breakpoint(code))) {
- sprintf(reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]);
- } else {
- sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code);
- }
- }
- break;
- case 0x301:
- p = arguments;
- if (arguments) {
- code = strtol(arguments, &p, 16);
- }
- if (p == arguments) {
- while (first != NULL) delete_breakpoint(first);
- sprintf(reply, "401 All breakpoints deleted.\r\n");
- } else {
- if ((bp = find_breakpoint(code))) {
- delete_breakpoint(bp);
- sprintf(reply, "401 Breakpoint %X deleted.\r\n", code);
- } else {
- sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code);
- }
- }
- break;
- case 0x310:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 310 command '%s'\r\n", arguments);
- break;
- }
-// if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
-// sprintf(reply, "531 Invalid address %08X\r\n", address);
-// break;
-// }
- code = add_breakpoint(BE, address);
- sprintf(reply, "410 %X\r\n", code);
- break;
- case 0x320:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 320 command '%s'\r\n", arguments);
- break;
- }
- if ((address < 0x80000000) || (address >= 0x80200000)) {
- sprintf(reply, "532 Invalid address %08X\r\n", address);
- break;
- }
- code = add_breakpoint(BR1, address);
- sprintf(reply, "420 %X\r\n", code);
- break;
- case 0x321:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 321 command '%s'\r\n", arguments);
- break;
- }
- if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) {
- sprintf(reply, "532 Invalid address %08X\r\n", address);
- break;
- }
- code = add_breakpoint(BR2, address);
- sprintf(reply, "421 %X\r\n", code);
- break;
- case 0x322:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 322 command '%s'\r\n", arguments);
- break;
- }
- if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
- sprintf(reply, "532 Invalid address %08X\r\n", address);
- break;
- }
- code = add_breakpoint(BR4, address);
- sprintf(reply, "422 %X\r\n", code);
- break;
- case 0x330:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 330 command '%s'\r\n", arguments);
- break;
- }
- if ((address < 0x80000000) || (address >= 0x80200000)) {
- sprintf(reply, "533 Invalid address %08X\r\n", address);
- break;
- }
- code = add_breakpoint(BW1, address);
- sprintf(reply, "430 %X\r\n", code);
- break;
- case 0x331:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 331 command '%s'\r\n", arguments);
- break;
- }
- if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) {
- sprintf(reply, "533 Invalid address %08X\r\n", address);
- break;
- }
- code = add_breakpoint(BW2, address);
- sprintf(reply, "431 %X\r\n", code);
- break;
- case 0x332:
- if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
- sprintf(reply, "500 Malformed 332 command '%s'\r\n", arguments);
- break;
- }
- if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
- sprintf(reply, "533 Invalid address %08X\r\n", address);
- break;
- }
- code = add_breakpoint(BW4, address);
- sprintf(reply, "432 %X\r\n", code);
- break;
- case 0x390:
- paused = 1;
- sprintf(reply, "490 Paused\r\n");
- break;
- case 0x391:
- paused = 0;
- sprintf(reply, "491 Resumed\r\n");
- break;
- case 0x395:
- p = arguments;
- if (arguments) {
- trace = strtol(arguments, &p, 10);
- }
- if (p == arguments) {
- trace = 1;
- }
- paused = 0;
- sprintf(reply, "495 Tracing\r\n");
- break;
- case 0x398:
- paused = 0;
- trace = 0;
- reset = 2;
- sprintf(reply, "498 Soft resetting\r\n");
- break;
- case 0x399:
- paused = 0;
- trace = 0;
- reset = 1;
- sprintf(reply, "499 Resetting\r\n");
- break;
- default:
- sprintf(reply, "500 Unknown command '%s'\r\n", cmd);
- break;
- }
- WriteSocket(reply, strlen(reply));
-
- if (dumping) {
- WriteSocket(dump, size);
- }
-
- if (save) {
- free(save);
- }
- }
-}
-
-void DebugCheckBP(u32 address, enum breakpoint_types type) {
- breakpoint_t *bp;
- char reply[512];
-
- if (!debugger_active || reset)
- return;
- for (bp = first; bp; bp = next_breakpoint(bp)) {
- if ((bp->type == type) && (bp->address == address)) {
- sprintf(reply, "030 %X@%08X\r\n", bp->number, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- return;
- }
- }
- if (breakmp_e && type == BE) {
- if (!IsMapMarked(address, MAP_EXEC)) {
- sprintf(reply, "010 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (breakmp_r8 && type == BR1) {
- if (!IsMapMarked(address, MAP_R8)) {
- sprintf(reply, "011 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (breakmp_r16 && type == BR2) {
- if (!IsMapMarked(address, MAP_R16)) {
- sprintf(reply, "012 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (breakmp_r32 && type == BR4) {
- if (!IsMapMarked(address, MAP_R32)) {
- sprintf(reply, "013 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (breakmp_w8 && type == BW1) {
- if (!IsMapMarked(address, MAP_W8)) {
- sprintf(reply, "014 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (breakmp_w16 && type == BW2) {
- if (!IsMapMarked(address, MAP_W16)) {
- sprintf(reply, "015 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (breakmp_w32 && type == BW4) {
- if (!IsMapMarked(address, MAP_W32)) {
- sprintf(reply, "016 %08X@%08X\r\n", address, psxRegs.pc);
- WriteSocket(reply, strlen(reply));
- paused = 1;
- }
- }
- if (mapping_r8 && type == BR1) MarkMap(address, MAP_R8);
- if (mapping_r16 && type == BR2) MarkMap(address, MAP_R16);
- if (mapping_r32 && type == BR4) MarkMap(address, MAP_R32);
- if (mapping_w8 && type == BW1) MarkMap(address, MAP_W8);
- if (mapping_w16 && type == BW2) MarkMap(address, MAP_W16);
- if (mapping_w32 && type == BW4) MarkMap(address, MAP_W32);
- }
+/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2003 Pcsx 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, see <http://www.gnu.org/licenses>. + */ + +#include "psxcommon.h" +#include "r3000a.h" +#include "debug.h" +#include "socket.h" + +/* +PCSXR Debug console protocol description, version 1.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Commands number are formatted using %03X (yes) +Registers number are formatted using %02X. +Breakpoints numbers are formatted using %X +All other values are formatted using %08X, unless specified. + + +Client inputs: +~~~~~~~~~~~~~ +Basic commands (1xx): +-------------------- +100 <message> + Sends a dumb message. Will be replied with a 200 reply, followed by the message. +101 + Gets PCSXR version. +102 + Gets protocol version. +103 + Gets status +110 + Gets PC. +111 [reg] + Gets GP register, or all, if no argument. +112 + Gets LO/HI registers. +113 [reg] + Gets COP0 register, or all, if no argument. +114 [reg] + Gets COP2 control register, or all, if no argument. +115 [reg] + Gets COP2 data register, or all, if no argument. +119 [pc] + Disassemble current PC, or given PC. +121 <reg>=<value> + Sets a GP register. Will return a 221 message. +122 <LO|HI>=<value> + Sets LO or HI register. Will return a 222 message. +123 <reg>=<value> + Sets a COP0 register. Will return a 223 message. +124 <reg>=<value> + Sets a COP2 control register. Will return a 224 message. +125 <reg>=<value> + Sets a COP2 data register. Will return a 225 message. +130 <size>@<addr> + Dumps a range of memory, of size bytes starting at addr. +140 <size>@<addr> + Sets a range of memory, of size bytes starting at addr. + Will have to send immediately exactly size bytes afterward. +150 [number] + Starts/reset mapping execution flow, or stop it if number = 0 +151 [number] + Starts/reset mapping read8 flow, or stop it if number = 0 +152 [number] + Starts/reset mapping read16 flow, or stop it if number = 0 +153 [number] + Starts/reset mapping read32 flow, or stop it if number = 0 +154 [number] + Starts/reset mapping write8 flow, or stop it if number = 0 +155 [number] + Starts/reset mapping write16 flow, or stop it if number = 0 +156 [number] + Starts/reset mapping write32 flow, or stop it if number = 0 +160 [number] + Breaks on map exec flow, or stop it if number = 0 +161 [number] + Breaks on map read8 flow, or stop it if number = 0 +162 [number] + Breaks on map read16 flow, or stop it if number = 0 +163 [number] + Breaks on map read32 flow, or stop it if number = 0 +164 [number] + Breaks on map write8 flow, or stop it if number = 0 +165 [number] + Breaks on map write16 flow, or stop it if number = 0 +166 [number] + Breaks on map write32 flow, or stop it if number = 0 +170 + Dumps the execution flow map in an IDC file + +Execution flow control commands (3xx): +------------------------------------- +300 [number] + Get a list of the actual breakpoints. Will get '400' answers. +301 [number] + Deletes a breakpoint, or all, if no arguments. +310 <address> + Sets an exec breakpoint. +320 <address> + Sets a read breakpoint, 1 byte / 8 bits. +321 <address> + Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address. +322 <address> + Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned. +330 <address> + Sets a write breakpoint, 1 byte / 8 bits. +331 <address> + Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address. +332 <address> + Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned. +390 + Pauses execution. Equivalents to a breakpoint. +391 + Restarts execution. +395 [number] + Traces execution, 1 instruction by default. Formatted using %i +398 + Soft (quick) resets. +399 + Resets. + + +Server outputs: +~~~~~~~~~~~~~~ +Spontaneous messages (0xx): +-------------------------- +000 <message> + Greeting banner. +010 / 011 / 012 / 013 / 014 / 015 / 016 + Execution hit mapping flow automatic breakpoint. +030 <number>@<PC> + Execution hit breakpoint, PCSXR is paused. Displays PC's value. + +Basic commands acknowledge (2xx): +-------------------------------- +200 <message> + Sends a dumb message. +201 <message> + Returns PCSXR version. +202 <message> + Returns protocol version. +203 <status> + status = 0: running; = 1: paused; = 2: trace +210 PC=<value> + Displays current PC value. +211 <reg>=<value> + Displays one GP register value. +212 LO=<value> HI=<value> + Displays LO/HI registers. +213 <reg>=<value> + Displays one COP0 register value. +214 <reg>=<value> + Displays one COP2 control register value. +215 <reg>=<value> + Displays one COP2 data register value. +219 <message> + Displays one line of disassembled code. +221 <reg>=<value> + Displays one GP register value, ack for modification. +222 LO=<value> HI=<value> + Displays LO/HI registers, ack for modification. +223 <reg>=<value> + Displays one COP0 register value, ack for modification. +224 <reg>=<value> + Displays one COP2 control register value, ack for modification. +225 <reg>=<value> + Displays one COP2 data register value, ack for modification. +230 <size>@<addr> + Dumping memory. Will then raw outputs size bytes. +240 <size>@<addr> + Memory set acknowledge. +250 / 251 / 252 / 253 / 254 / 255 / 256 + Acknolwedge of 15x commands. +260 / 261 / 262 / 263 / 264 / 265 / 266 + Acknolwedge of 16x commands. +270 + Acknolwedge of 170 command. + +Execution flow control commands acknowledge (4xx): +------------------------------------------------- +400 <number>@<address>-<type> + Displays a breakpoint, where 'type' can be of BE, BR1, BR2, BR4, BW1, BW2 or BW4. +401 <message> + Breakpoint deleting acknowledge. +410, 420, 421, 422, 430, 431, 432 <number> + Breakpoint adding acknowledge. Returns the number of the added breakpoint. +490 <message> + Pausing. +491 <message> + Resuming. +495 <message> + Tracing. +498 <message> + Soft resetting. +499 <message> + Resetting. + +Error messages (5xx): +-------------------- +500 <message> + Command not understood. +511 <message> + Invalid GPR register. +512 <message> + Invalid LO/HI register. +513, 514 <message> + Invalid range or address. +530 <message> + Non existant breakpoint. +531, 532, 533 <message> + Invalid breakpoint address. +*/ + +static int debugger_active = 0, paused = 0, trace = 0, reset = 0, resetting = 0; +static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0; +static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0; + +static void ProcessCommands(); + +static u8 *MemoryMap = NULL; + +enum { + MAP_EXEC = 1, + MAP_R8 = 2, + MAP_R16 = 4, + MAP_R32 = 8, + MAP_W8 = 16, + MAP_W16 = 32, + MAP_W32 = 64, + MAP_EXEC_JAL = 128, +}; + +char *breakpoint_type_names[] = { + "E", "R1", "R2", "R4", "W1", "W2", "W4" +}; + +typedef struct breakpoint_s { + struct breakpoint_s *next, *prev; + int number, type; + u32 address; +} breakpoint_t; + +static breakpoint_t *first = NULL; + +int add_breakpoint(int type, u32 address) { + breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t)); + + bp->type = type; + bp->address = address; + + if (first) { + bp->number = first->prev->number + 1; + bp->next = first; + bp->prev = first->prev; + first->prev = bp; + bp->prev->next = bp; + } else { + first = bp; + bp->number = 1; + bp->next = bp; + bp->prev = bp; + } + + return bp->number; +} + +void delete_breakpoint(breakpoint_t * bp) { + if (bp == first) { + if (bp->next == bp) { + first = NULL; + } else { + first = bp->next; + } + } + + bp->next->prev = bp->prev; + bp->prev->next = bp->next; + + free(bp); +} + +breakpoint_t *next_breakpoint(breakpoint_t *bp) { + return bp->next != first ? bp->next : 0; +} + +breakpoint_t *find_breakpoint(int number) { + breakpoint_t *p; + + for (p = first; p; p = next_breakpoint(p)) { + if (p->number == number) + return p; + } + + return 0; +} + +void StartDebugger() { + if (debugger_active) + return; + + MemoryMap = (u8 *)malloc(0x200000); + if (MemoryMap == NULL) { + SysMessage(_("Error allocating memory")); + return; + } + + if (StartServer() == -1) { + SysPrintf(_("Unable to start debug server.\n")); + return; + } + + SysPrintf(_("Debugger started.\n")); + debugger_active = 1; +} + +void StopDebugger() { + if (debugger_active) { + StopServer(); + SysPrintf(_("Debugger stopped.\n")); + } + + if (MemoryMap != NULL) { + free(MemoryMap); + MemoryMap = NULL; + } + + while (first != NULL) delete_breakpoint(first); + + debugger_active = 0; +} + +void PauseDebugger() { + trace = 0; + paused = 1; +} + +void ResumeDebugger() { + trace = 0; + paused = 0; +} + +void DebugVSync() { + if (!debugger_active || resetting) + return; + + if (reset) { + resetting = 1; + CheckCdrom(); + SysReset(); + if (reset == 2) + LoadCdrom(); + reset = resetting = 0; + return; + } + + GetClient(); + ProcessCommands(); +} + +void MarkMap(u32 address, int mask) { + if ((address & 0xff000000) != 0x80000000) return; + MemoryMap[address & 0x001fffff] |= mask; +} + +int IsMapMarked(u32 address, int mask) { + return (MemoryMap[address & 0x001fffff] & mask) != 0; +} + +void ProcessDebug() { + if (!debugger_active || reset || resetting) + return; + if (trace) { + if (!(--trace)) { + paused = 1; + } + } + if (!paused) { + DebugCheckBP(psxRegs.pc, BE); + } + if (mapping_e) { + MarkMap(psxRegs.pc, MAP_EXEC); + if ((psxRegs.code >> 26) == 3) { + MarkMap(_JumpTarget_, MAP_EXEC_JAL); + } + if (((psxRegs.code >> 26) == 0) && ((psxRegs.code & 0x3F) == 9)) { + MarkMap(_Rd_, MAP_EXEC_JAL); + } + } + while (paused) { + GetClient(); + ProcessCommands(); + GPU_updateLace(); + SysUpdate(); + } +} + +static void ProcessCommands() { + int code, i, dumping; + FILE *sfile; + char cmd[257], *arguments, *p, reply[10240], *save, *dump; + u32 reg, value, size, address; + breakpoint_t *bp; + + if (!HasClient()) + return; + if (ReadSocket(cmd, 256) > 0) { + arguments = NULL; + if (strlen(cmd) <= 2) { + code = 0; + } else if (strlen(cmd) == 3) { + code = strtol(cmd, 0, 16); + } else if (!(isxdigit(cmd[0]) && isxdigit(cmd[1]) && isxdigit(cmd[2]) && (cmd[3] == 0x20))) { + code = 0; + } else if (sscanf(cmd, "%3X ", &code) != 1) { + code = 0; + } else { + arguments = cmd + 4; + } + code = strtol(cmd, &arguments, 16); + while (arguments && *arguments && *arguments == 0x20) + arguments++; + + if (*arguments == '\0') + arguments = NULL; + + dumping = 0; + save = NULL; + + switch (code) { + case 0x100: + sprintf(reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments); + break; + case 0x101: + sprintf(reply, "201 %s\r\n", PACKAGE_VERSION); + break; + case 0x102: + sprintf(reply, "202 1.0\r\n"); + break; + case 0x103: + sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0); + break; + case 0x110: + sprintf(reply, "210 PC=%08X\r\n", psxRegs.pc); + break; + case 0x111: + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s211 %02X=%08X\r\n", reply, i, psxRegs.GPR.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "211 %02X=%08X\r\n", code, psxRegs.GPR.r[code]); + } else { + sprintf(reply, "511 Invalid GPR register: %X\r\n", code); + } + } + break; + case 0x112: + sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); + break; + case 0x113: + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "511 Malformed 113 command '%s'\r\n", cmd); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s213 %02X=%08X\r\n", reply, i, psxRegs.CP0.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "213 %02X=%08X\r\n", code, psxRegs.CP0.r[code]); + } else { + sprintf(reply, "511 Invalid COP0 register: %X\r\n", code); + } + } + break; + case 0x114: + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "511 Malformed 114 command '%s'\r\n", cmd); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s214 %02X=%08X\r\n", reply, i, psxRegs.CP2C.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "214 %02X=%08X\r\n", code, psxRegs.CP2C.r[code]); + } else { + sprintf(reply, "511 Invalid COP2C register: %X\r\n", code); + } + } + break; + case 0x115: + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s215 %02X=%08X\r\n", reply, i, psxRegs.CP2D.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "215 %02X=%08X\r\n", code, psxRegs.CP2D.r[code]); + } else { + sprintf(reply, "511 Invalid COP2D register: %X\r\n", code); + } + } + break; + case 0x119: + if (arguments) { + if (sscanf(arguments, "%08X", &code) != 1) { + sprintf(reply, "511 Malformed 119 command '%s'\r\n", cmd); + break; + } + } + if (!arguments) + code = psxRegs.pc; + + sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code)); + break; + case 0x121: + if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { + sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments); + break; + } + + if (reg < 32) { + psxRegs.GPR.r[reg] = value; + sprintf(reply, "221 %02X=%08X\r\n", reg, value); + } else { + sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg); + } + break; + case 0x122: + if (!arguments || strncmp(arguments, "HI=", 3) == 0) { + reg = 33; + } else if (arguments && strncmp(arguments, "LO=", 3) == 0) { + reg = 32; + } else { + arguments[2] = 0; + sprintf(reply, "512 Invalid LO/HI register: '%s'\r\n", arguments); + break; + } + + if (sscanf(arguments + 3, "%08X", &value) != 1) { + sprintf(reply, "500 Malformed 122 command '%s'\r\n", arguments); + } else { + psxRegs.GPR.r[reg] = value; + sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); + } + break; + case 0x123: + if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { + sprintf(reply, "500 Malformed 123 command '%s'\r\n", arguments); + break; + } + + if (reg < 32) { + psxRegs.CP0.r[reg] = value; + sprintf(reply, "223 %02X=%08X\r\n", reg, value); + } else { + sprintf(reply, "512 Invalid COP0 register: %02X\r\n", reg); + } + break; + case 0x124: + if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { + sprintf(reply, "500 Malformed 124 command '%s'\r\n", arguments); + break; + } + + if (reg < 32) { + psxRegs.CP2C.r[reg] = value; + sprintf(reply, "224 %02X=%08X\r\n", reg, value); + } else { + sprintf(reply, "512 Invalid COP2C register: %02X\r\n", reg); + } + break; + case 0x125: + if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { + sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments); + break; + } + + if (reg < 32) { + psxRegs.CP2D.r[reg] = value; + sprintf(reply, "225 %02X=%08X\r\n", reg, value); + } else { + sprintf(reply, "512 Invalid COP2D register: %02X\r\n", reg); + } + break; + case 0x130: + if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { + sprintf(reply, "500 Malformed 130 command '%s'\r\n", arguments); + break; + } + + if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { + sprintf(reply, "230 %08X@%08X\r\n", size, address); + dump = (char *) PSXM(address); + dumping = 1; + } else { + sprintf(reply, "513 Invalid address or range: '%s'\r\n", arguments); + } + break; + case 0x140: + if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { + sprintf(reply, "500 Malformed 140 command '%s'\r\n", arguments); + break; + } + + if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { + sprintf(reply, "240 %08X@%08X\r\n", size, address); + RawReadSocket((char *)PSXM(address), size); + } else { + sprintf(reply, "514 Invalid address or range: '%s'\r\n", arguments); + } + break; + case 0x150: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 150 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_e = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_EXEC; + MemoryMap[i] &= ~MAP_EXEC_JAL; + } + } else { + mapping_e = 0; + } + sprintf(reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x151: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 151 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_r8 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_R8; + } + } else { + mapping_r8 = 0; + } + sprintf(reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x152: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 152 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_r16 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_R16; + } + } else { + mapping_r16 = 0; + } + sprintf(reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x153: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 153 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_r32 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_R32; + } + } else { + mapping_r32 = 0; + } + sprintf(reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x154: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 154 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_w8 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_W8; + } + } else { + mapping_w8 = 0; + } + sprintf(reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x155: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 155 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_w16 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_W16; + } + } else { + mapping_w16 = 0; + } + sprintf(reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x156: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 156 command '%s'\r\n", cmd); + break; + } + } + if (code) { + mapping_w32 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_W32; + } + } else { + mapping_w32 = 0; + } + sprintf(reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x160: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 160 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_e = 1; + } else { + breakmp_e = 0; + } + sprintf(reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x161: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 161 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_r8 = 1; + } else { + breakmp_r8 = 0; + } + sprintf(reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x162: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 162 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_r16 = 1; + } else { + breakmp_r16 = 0; + } + sprintf(reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x163: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 163 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_r32 = 1; + } else { + breakmp_r32 = 0; + } + sprintf(reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x164: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 164 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_w8 = 1; + } else { + breakmp_w8 = 0; + } + sprintf(reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x165: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 165 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_w16 = 1; + } else { + breakmp_w16 = 0; + } + sprintf(reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x166: + code = 1; + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(reply, "500 Malformed 166 command '%s'\r\n", cmd); + break; + } + } + if (code) { + breakmp_w32 = 1; + } else { + breakmp_w32 = 0; + } + sprintf(reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped"); + break; + case 0x170: + sfile = fopen("flow.idc", "wb"); + fprintf(sfile, "#include <idc.idc>\r\n\r\n"); + fprintf(sfile, "static main(void) {\r\n"); + for (i = 0; i < 0x00200000; i++) { + if (IsMapMarked(i, MAP_EXEC_JAL)) { + fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i); + } + } + fprintf(sfile, "}\r\n"); + fclose(sfile); + sfile = fopen("markcode.idc", "wb"); + fprintf(sfile, "#include <idc.idc>\r\n\r\n"); + fprintf(sfile, "static main(void) {\r\n"); + for (i = 0; i < 0x00200000; i++) { + if (IsMapMarked(i, MAP_EXEC)) { + fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i); + } + } + fprintf(sfile, "}\r\n"); + fclose(sfile); + sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n"); + break; + case 0x300: + p = arguments; + if (arguments) { + code = strtol(arguments, &p, 16); + } + if (p == arguments) { + if (first) { + reply[0] = 0; + for (bp = first; bp; bp = next_breakpoint(bp)) { + sprintf(reply, "%s400 %X@%08X-%s\r\n", reply, bp->number, bp->address, breakpoint_type_names[bp->type]); + } + } else { + sprintf(reply, "530 No breakpoint\r\n"); + } + } else { + if ((bp = find_breakpoint(code))) { + sprintf(reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); + } else { + sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + } + } + break; + case 0x301: + p = arguments; + if (arguments) { + code = strtol(arguments, &p, 16); + } + if (p == arguments) { + while (first != NULL) delete_breakpoint(first); + sprintf(reply, "401 All breakpoints deleted.\r\n"); + } else { + if ((bp = find_breakpoint(code))) { + delete_breakpoint(bp); + sprintf(reply, "401 Breakpoint %X deleted.\r\n", code); + } else { + sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + } + } + break; + case 0x310: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 310 command '%s'\r\n", arguments); + break; + } +// if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { +// sprintf(reply, "531 Invalid address %08X\r\n", address); +// break; +// } + code = add_breakpoint(BE, address); + sprintf(reply, "410 %X\r\n", code); + break; + case 0x320: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 320 command '%s'\r\n", arguments); + break; + } + if ((address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "532 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(BR1, address); + sprintf(reply, "420 %X\r\n", code); + break; + case 0x321: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 321 command '%s'\r\n", arguments); + break; + } + if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "532 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(BR2, address); + sprintf(reply, "421 %X\r\n", code); + break; + case 0x322: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 322 command '%s'\r\n", arguments); + break; + } + if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "532 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(BR4, address); + sprintf(reply, "422 %X\r\n", code); + break; + case 0x330: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 330 command '%s'\r\n", arguments); + break; + } + if ((address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "533 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(BW1, address); + sprintf(reply, "430 %X\r\n", code); + break; + case 0x331: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 331 command '%s'\r\n", arguments); + break; + } + if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "533 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(BW2, address); + sprintf(reply, "431 %X\r\n", code); + break; + case 0x332: + if (!arguments || sscanf(arguments, "%08X", &address) != 1) { + sprintf(reply, "500 Malformed 332 command '%s'\r\n", arguments); + break; + } + if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "533 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(BW4, address); + sprintf(reply, "432 %X\r\n", code); + break; + case 0x390: + paused = 1; + sprintf(reply, "490 Paused\r\n"); + break; + case 0x391: + paused = 0; + sprintf(reply, "491 Resumed\r\n"); + break; + case 0x395: + p = arguments; + if (arguments) { + trace = strtol(arguments, &p, 10); + } + if (p == arguments) { + trace = 1; + } + paused = 0; + sprintf(reply, "495 Tracing\r\n"); + break; + case 0x398: + paused = 0; + trace = 0; + reset = 2; + sprintf(reply, "498 Soft resetting\r\n"); + break; + case 0x399: + paused = 0; + trace = 0; + reset = 1; + sprintf(reply, "499 Resetting\r\n"); + break; + default: + sprintf(reply, "500 Unknown command '%s'\r\n", cmd); + break; + } + WriteSocket(reply, strlen(reply)); + + if (dumping) { + WriteSocket(dump, size); + } + + if (save) { + free(save); + } + } +} + +void DebugCheckBP(u32 address, enum breakpoint_types type) { + breakpoint_t *bp; + char reply[512]; + + if (!debugger_active || reset) + return; + for (bp = first; bp; bp = next_breakpoint(bp)) { + if ((bp->type == type) && (bp->address == address)) { + sprintf(reply, "030 %X@%08X\r\n", bp->number, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + return; + } + } + if (breakmp_e && type == BE) { + if (!IsMapMarked(address, MAP_EXEC)) { + sprintf(reply, "010 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_r8 && type == BR1) { + if (!IsMapMarked(address, MAP_R8)) { + sprintf(reply, "011 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_r16 && type == BR2) { + if (!IsMapMarked(address, MAP_R16)) { + sprintf(reply, "012 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_r32 && type == BR4) { + if (!IsMapMarked(address, MAP_R32)) { + sprintf(reply, "013 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_w8 && type == BW1) { + if (!IsMapMarked(address, MAP_W8)) { + sprintf(reply, "014 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_w16 && type == BW2) { + if (!IsMapMarked(address, MAP_W16)) { + sprintf(reply, "015 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_w32 && type == BW4) { + if (!IsMapMarked(address, MAP_W32)) { + sprintf(reply, "016 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (mapping_r8 && type == BR1) MarkMap(address, MAP_R8); + if (mapping_r16 && type == BR2) MarkMap(address, MAP_R16); + if (mapping_r32 && type == BR4) MarkMap(address, MAP_R32); + if (mapping_w8 && type == BW1) MarkMap(address, MAP_W8); + if (mapping_w16 && type == BW2) MarkMap(address, MAP_W16); + if (mapping_w32 && type == BW4) MarkMap(address, MAP_W32); + } diff --git a/libpcsxcore/decode_xa.c b/libpcsxcore/decode_xa.c index 96f7c958..8347f597 100644..100755 --- a/libpcsxcore/decode_xa.c +++ b/libpcsxcore/decode_xa.c @@ -1,367 +1,367 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* XA audio decoding functions (Kazzuya).
-*/
-
-#include "decode_xa.h"
-
-#define FIXED
-
-#define NOT(_X_) (!(_X_))
-#define XACLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;}
-
-#define SH 4
-#define SHC 10
-
-//============================================
-//=== ADPCM DECODING ROUTINES
-//============================================
-
-#ifndef FIXED
-static double K0[4] = {
- 0.0,
- 0.9375,
- 1.796875,
- 1.53125
-};
-
-static double K1[4] = {
- 0.0,
- 0.0,
- -0.8125,
- -0.859375
-};
-#else
-static int K0[4] = {
- 0.0 * (1<<SHC),
- 0.9375 * (1<<SHC),
- 1.796875 * (1<<SHC),
- 1.53125 * (1<<SHC)
-};
-
-static int K1[4] = {
- 0.0 * (1<<SHC),
- 0.0 * (1<<SHC),
- -0.8125 * (1<<SHC),
- -0.859375 * (1<<SHC)
-};
-#endif
-
-#define BLKSIZ 28 /* block size (32 - 4 nibbles) */
-
-//===========================================
-void ADPCM_InitDecode(ADPCM_Decode_t *decp) {
- decp->y0 = 0;
- decp->y1 = 0;
-}
-
-//===========================================
-#ifndef FIXED
-#define IK0(fid) ((int)((-K0[fid]) * (1<<SHC)))
-#define IK1(fid) ((int)((-K1[fid]) * (1<<SHC)))
-#else
-#define IK0(fid) (-K0[fid])
-#define IK1(fid) (-K1[fid])
-#endif
-
-static __inline void ADPCM_DecodeBlock16( ADPCM_Decode_t *decp, u8 filter_range, const void *vblockp, short *destp, int inc ) {
- int i;
- int range, filterid;
- s32 fy0, fy1;
- const u16 *blockp;
-
- blockp = (const unsigned short *)vblockp;
- filterid = (filter_range >> 4) & 0x0f;
- range = (filter_range >> 0) & 0x0f;
-
- fy0 = decp->y0;
- fy1 = decp->y1;
-
- for (i = BLKSIZ/4; i; --i) {
- s32 y;
- s32 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;
-
- XACLAMP( x0, -32768<<SH, 32767<<SH ); *destp = x0 >> SH; destp += inc;
- XACLAMP( x1, -32768<<SH, 32767<<SH ); *destp = x1 >> SH; destp += inc;
- XACLAMP( x2, -32768<<SH, 32767<<SH ); *destp = x2 >> SH; destp += inc;
- XACLAMP( x3, -32768<<SH, 32767<<SH ); *destp = x3 >> 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
- if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A
- 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;
-
- for (k=0; k < 14; k++, sound_datap2 += 8) {
- *(datap++) = (u16)sound_datap2[0] |
- (u16)(sound_datap2[4] << 8);
- }
-
- ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data,
- destp+0, 2 );
-
- datap = data;
- sound_datap2 = sound_datap + i;
- for (k=0; k < 14; k++, sound_datap2 += 8) {
- *(datap++) = (u16)sound_datap2[0] |
- (u16)(sound_datap2[4] << 8);
- }
- ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data,
- destp+1, 2 );
-
- destp += 28*2;
- }
- }
- } else { // level B/C
- 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;
-
- 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;
- 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
- if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A
- 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;
- for (k=0; k < 14; k++, sound_datap2 += 8) {
- *(datap++) = (u16)sound_datap2[0] |
- (u16)(sound_datap2[4] << 8);
- }
- ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data,
- destp, 1 );
-
- destp += 28;
-
- datap = data;
- sound_datap2 = sound_datap + i;
- for (k=0; k < 14; k++, sound_datap2 += 8) {
- *(datap++) = (u16)sound_datap2[0] |
- (u16)(sound_datap2[4] << 8);
- }
- ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data,
- destp, 1 );
-
- destp += 28;
- }
- }
- } else { // level B/C
- 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;
- 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;
- 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
-//================================================================
-s32 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 );
- }
-*/
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* XA audio decoding functions (Kazzuya). +*/ + +#include "decode_xa.h" + +#define FIXED + +#define NOT(_X_) (!(_X_)) +#define XACLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} + +#define SH 4 +#define SHC 10 + +//============================================ +//=== ADPCM DECODING ROUTINES +//============================================ + +#ifndef FIXED +static double K0[4] = { + 0.0, + 0.9375, + 1.796875, + 1.53125 +}; + +static double K1[4] = { + 0.0, + 0.0, + -0.8125, + -0.859375 +}; +#else +static int K0[4] = { + 0.0 * (1<<SHC), + 0.9375 * (1<<SHC), + 1.796875 * (1<<SHC), + 1.53125 * (1<<SHC) +}; + +static int K1[4] = { + 0.0 * (1<<SHC), + 0.0 * (1<<SHC), + -0.8125 * (1<<SHC), + -0.859375 * (1<<SHC) +}; +#endif + +#define BLKSIZ 28 /* block size (32 - 4 nibbles) */ + +//=========================================== +void ADPCM_InitDecode(ADPCM_Decode_t *decp) { + decp->y0 = 0; + decp->y1 = 0; +} + +//=========================================== +#ifndef FIXED +#define IK0(fid) ((int)((-K0[fid]) * (1<<SHC))) +#define IK1(fid) ((int)((-K1[fid]) * (1<<SHC))) +#else +#define IK0(fid) (-K0[fid]) +#define IK1(fid) (-K1[fid]) +#endif + +static __inline void ADPCM_DecodeBlock16( ADPCM_Decode_t *decp, u8 filter_range, const void *vblockp, short *destp, int inc ) { + int i; + int range, filterid; + s32 fy0, fy1; + const u16 *blockp; + + blockp = (const unsigned short *)vblockp; + filterid = (filter_range >> 4) & 0x0f; + range = (filter_range >> 0) & 0x0f; + + fy0 = decp->y0; + fy1 = decp->y1; + + for (i = BLKSIZ/4; i; --i) { + s32 y; + s32 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; + + XACLAMP( x0, -32768<<SH, 32767<<SH ); *destp = x0 >> SH; destp += inc; + XACLAMP( x1, -32768<<SH, 32767<<SH ); *destp = x1 >> SH; destp += inc; + XACLAMP( x2, -32768<<SH, 32767<<SH ); *destp = x2 >> SH; destp += inc; + XACLAMP( x3, -32768<<SH, 32767<<SH ); *destp = x3 >> 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 + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + 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; + + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } else { // level B/C + 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; + + 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; + 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 + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + 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; + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } else { // level B/C + 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; + 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; + 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 +//================================================================ +s32 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/libpcsxcore/disr3000a.c b/libpcsxcore/disr3000a.c index 28bbdc53..2140008f 100644..100755 --- a/libpcsxcore/disr3000a.c +++ b/libpcsxcore/disr3000a.c @@ -1,337 +1,337 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* R3000A disassembler.
-*/
-
-#include "psxcommon.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 *disRNameCP2D[] = {
- "VXY0", "VZ0", "VXY1", "VZ1", "VXY2", "VZ2", "RGB", "OTZ",
- "IR0", "IR1", "IR2", "IR3", "SXY0", "SXY1", "SXY2", "SXYP",
- "SZ0", "SZ1", "SZ2", "SZ3", "RGB0", "RGB1", "RGB2", "RES1",
- "MAC0", "MAC1", "MAC2", "MAC3", "IRGB", "ORGB", "LZCS", "LZCR"};
-
-static char *disRNameCP2C[] = {
- "R11R12", "R13R21", "R22R23", "R31R32", "R33", "TRX", "TRY", "TRZ",
- "L11L12", "L13L21", "L22L23", "L31L32", "L33", "RBK", "BBK", "GBK",
- "LR1LR2", "LR3LG1", "LG2LG3", "LB1LB2", "LB3", "RFC", "GFC", "BFC",
- "OFX", "OFY", "H", "DQA", "DQB", "ZSF3", "ZSF4", "FLAG"};
-
-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.8x %8.8x:", 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.8x (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i])
-#define dCP0(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i])
-#define dCP2D(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP2D.r[i], disRNameCP2D[i])
-#define dCP2C(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP2C.r[i], disRNameCP2C[i])
-#define dHI() sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.hi, "hi")
-#define dLO() sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.lo, "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 dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_])
-#define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_)
-#define dCode() sprintf(ostr, "%s %8.8x,", 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(disHLE, dName("HLE"))
-
-
-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_); dCP2C(_Rd_);)
-MakeDisF(disMTC2, dName("MTC2"); dCP2C(_Rd_); dGPR(_Rt_);)
-MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_); dCP2C(_Rd_);)
-MakeDisF(disCTC2, dName("CTC2"); dCP2C(_Rd_); dGPR(_Rt_);)
-
-/*********************************************************
-* 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"); dCP2D(_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"); dCP2D(_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 , disHLE , disNULL, disNULL, disNULL , disNULL };
-
-MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc))
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* R3000A disassembler. +*/ + +#include "psxcommon.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 *disRNameCP2D[] = { + "VXY0", "VZ0", "VXY1", "VZ1", "VXY2", "VZ2", "RGB", "OTZ", + "IR0", "IR1", "IR2", "IR3", "SXY0", "SXY1", "SXY2", "SXYP", + "SZ0", "SZ1", "SZ2", "SZ3", "RGB0", "RGB1", "RGB2", "RES1", + "MAC0", "MAC1", "MAC2", "MAC3", "IRGB", "ORGB", "LZCS", "LZCR"}; + +static char *disRNameCP2C[] = { + "R11R12", "R13R21", "R22R23", "R31R32", "R33", "TRX", "TRY", "TRZ", + "L11L12", "L13L21", "L22L23", "L31L32", "L33", "RBK", "BBK", "GBK", + "LR1LR2", "LR3LG1", "LG2LG3", "LB1LB2", "LB3", "RFC", "GFC", "BFC", + "OFX", "OFY", "H", "DQA", "DQB", "ZSF3", "ZSF4", "FLAG"}; + +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.8x %8.8x:", 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.8x (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i]) +#define dCP0(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i]) +#define dCP2D(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP2D.r[i], disRNameCP2D[i]) +#define dCP2C(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP2C.r[i], disRNameCP2C[i]) +#define dHI() sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.hi, "hi") +#define dLO() sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.lo, "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 dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8x,", 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(disHLE, dName("HLE")) + + +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_); dCP2C(_Rd_);) +MakeDisF(disMTC2, dName("MTC2"); dCP2C(_Rd_); dGPR(_Rt_);) +MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_); dCP2C(_Rd_);) +MakeDisF(disCTC2, dName("CTC2"); dCP2C(_Rd_); dGPR(_Rt_);) + +/********************************************************* +* 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"); dCP2D(_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"); dCP2D(_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 , disHLE , disNULL, disNULL, disNULL , disNULL }; + +MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) diff --git a/libpcsxcore/gpu.c b/libpcsxcore/gpu.c index 9ade94ad..2b1e5b22 100644..100755 --- a/libpcsxcore/gpu.c +++ b/libpcsxcore/gpu.c @@ -1,186 +1,186 @@ -/* Copyright (c) 2010, shalma.
- * Portions Copyright (c) 2002, Pete Bernert.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "psxhw.h"
-#include "gpu.h"
-#include "psxdma.h"
-
-#define GPUSTATUS_ODDLINES 0x80000000
-#define GPUSTATUS_DMABITS 0x60000000 // Two bits
-#define GPUSTATUS_READYFORCOMMANDS 0x10000000
-#define GPUSTATUS_READYFORVRAM 0x08000000
-#define GPUSTATUS_IDLE 0x04000000
-
-#define GPUSTATUS_DISPLAYDISABLED 0x00800000
-#define GPUSTATUS_INTERLACED 0x00400000
-#define GPUSTATUS_RGB24 0x00200000
-#define GPUSTATUS_PAL 0x00100000
-#define GPUSTATUS_DOUBLEHEIGHT 0x00080000
-#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits
-#define GPUSTATUS_MASKENABLED 0x00001000
-#define GPUSTATUS_MASKDRAWN 0x00000800
-#define GPUSTATUS_DRAWINGALLOWED 0x00000400
-#define GPUSTATUS_DITHER 0x00000200
-
-// Taken from PEOPS SOFTGPU
-u32 lUsedAddr[3];
-
-static inline boolean CheckForEndlessLoop(u32 laddr) {
- if (laddr == lUsedAddr[1]) return TRUE;
- if (laddr == lUsedAddr[2]) return TRUE;
-
- if (laddr < lUsedAddr[0]) lUsedAddr[1] = laddr;
- else lUsedAddr[2] = laddr;
-
- lUsedAddr[0] = laddr;
-
- return FALSE;
-}
-
-static u32 gpuDmaChainSize(u32 addr) {
- u32 size;
- u32 DMACommandCounter = 0;
-
- lUsedAddr[0] = lUsedAddr[1] = lUsedAddr[2] = 0xffffff;
-
- // initial linked list ptr (word)
- size = 1;
-
- do {
- addr &= 0x1ffffc;
-
- if (DMACommandCounter++ > 2000000) break;
- if (CheckForEndlessLoop(addr)) break;
-
-
- // # 32-bit blocks to transfer
- size += psxMu8( addr + 3 );
-
-
- // next 32-bit pointer
- addr = psxMu32( addr & ~0x3 ) & 0xffffff;
- size += 1;
- } while (addr != 0xffffff);
-
-
- return size;
-}
-
-int gpuReadStatus() {
- int hard;
-
-
- // GPU plugin
- hard = GPU_readStatus();
-
-
- // Gameshark Lite - wants to see VRAM busy
- // - Must enable GPU 'Fake Busy States' hack
- if( (hard & GPUSTATUS_IDLE) == 0 )
- hard &= ~GPUSTATUS_READYFORVRAM;
-
- return hard;
-}
-
-void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
- u32 *ptr;
- u32 size;
-
- switch (chcr) {
- case 0x01000200: // vram2mem
-#ifdef PSXDMA_LOG
- PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
-#endif
- ptr = (u32 *)PSXM(madr);
- if (ptr == NULL) {
-#ifdef CPU_LOG
- CPU_LOG("*** DMA2 GPU - vram2mem *** NULL Pointer!!!\n");
-#endif
- break;
- }
- // BA blocks * BS words (word = 32-bits)
- size = (bcr >> 16) * (bcr & 0xffff);
- GPU_readDataMem(ptr, size);
- psxCpu->Clear(madr, size);
-
-#if 1
- // already 32-bit word size ((size * 4) / 4)
- GPUDMA_INT(size);
-#else
- // Experimental burst dma transfer (0.333x max)
- GPUDMA_INT(size/3);
-#endif
- return;
-
- case 0x01000201: // mem2vram
-#ifdef PSXDMA_LOG
- PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
-#endif
- ptr = (u32 *)PSXM(madr);
- if (ptr == NULL) {
-#ifdef CPU_LOG
- CPU_LOG("*** DMA2 GPU - mem2vram *** NULL Pointer!!!\n");
-#endif
- break;
- }
- // BA blocks * BS words (word = 32-bits)
- size = (bcr >> 16) * (bcr & 0xffff);
- GPU_writeDataMem(ptr, size);
-
-#if 1
- // already 32-bit word size ((size * 4) / 4)
- GPUDMA_INT(size);
-#else
- // Experimental burst dma transfer
- // - X-Files = 0.333333x max for videos
- GPUDMA_INT( size / 3 );
-#endif
- return;
-
- case 0x01000401: // dma chain
-#ifdef PSXDMA_LOG
- PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
-#endif
-
- size = gpuDmaChainSize(madr);
- GPU_dmaChain((u32 *)psxM, madr & 0x1fffff);
-
- // Tekken 3 = use 1.0 only (not 1.5x)
-
- // Einhander = parse linked list in pieces (todo)
- // Final Fantasy 4 = internal vram time (todo)
- // Rebel Assault 2 = parse linked list in pieces (todo)
- // Vampire Hunter D = allow edits to linked list (todo)
- GPUDMA_INT(size);
- return;
-
-#ifdef PSXDMA_LOG
- default:
- PSXDMA_LOG("*** DMA 2 - GPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
- break;
-#endif
- }
-
- HW_DMA2_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(2);
-}
-
-void gpuInterrupt() {
- HW_DMA2_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(2);
-}
+/* Copyright (c) 2010, shalma. + * Portions Copyright (c) 2002, Pete Bernert. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "psxhw.h" +#include "gpu.h" +#include "psxdma.h" + +#define GPUSTATUS_ODDLINES 0x80000000 +#define GPUSTATUS_DMABITS 0x60000000 // Two bits +#define GPUSTATUS_READYFORCOMMANDS 0x10000000 +#define GPUSTATUS_READYFORVRAM 0x08000000 +#define GPUSTATUS_IDLE 0x04000000 + +#define GPUSTATUS_DISPLAYDISABLED 0x00800000 +#define GPUSTATUS_INTERLACED 0x00400000 +#define GPUSTATUS_RGB24 0x00200000 +#define GPUSTATUS_PAL 0x00100000 +#define GPUSTATUS_DOUBLEHEIGHT 0x00080000 +#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits +#define GPUSTATUS_MASKENABLED 0x00001000 +#define GPUSTATUS_MASKDRAWN 0x00000800 +#define GPUSTATUS_DRAWINGALLOWED 0x00000400 +#define GPUSTATUS_DITHER 0x00000200 + +// Taken from PEOPS SOFTGPU +u32 lUsedAddr[3]; + +static inline boolean CheckForEndlessLoop(u32 laddr) { + if (laddr == lUsedAddr[1]) return TRUE; + if (laddr == lUsedAddr[2]) return TRUE; + + if (laddr < lUsedAddr[0]) lUsedAddr[1] = laddr; + else lUsedAddr[2] = laddr; + + lUsedAddr[0] = laddr; + + return FALSE; +} + +static u32 gpuDmaChainSize(u32 addr) { + u32 size; + u32 DMACommandCounter = 0; + + lUsedAddr[0] = lUsedAddr[1] = lUsedAddr[2] = 0xffffff; + + // initial linked list ptr (word) + size = 1; + + do { + addr &= 0x1ffffc; + + if (DMACommandCounter++ > 2000000) break; + if (CheckForEndlessLoop(addr)) break; + + + // # 32-bit blocks to transfer + size += psxMu8( addr + 3 ); + + + // next 32-bit pointer + addr = psxMu32( addr & ~0x3 ) & 0xffffff; + size += 1; + } while (addr != 0xffffff); + + + return size; +} + +int gpuReadStatus() { + int hard; + + + // GPU plugin + hard = GPU_readStatus(); + + + // Gameshark Lite - wants to see VRAM busy + // - Must enable GPU 'Fake Busy States' hack + if( (hard & GPUSTATUS_IDLE) == 0 ) + hard &= ~GPUSTATUS_READYFORVRAM; + + return hard; +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU + u32 *ptr; + u32 size; + + switch (chcr) { + case 0x01000200: // vram2mem +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + ptr = (u32 *)PSXM(madr); + if (ptr == NULL) { +#ifdef CPU_LOG + CPU_LOG("*** DMA2 GPU - vram2mem *** NULL Pointer!!!\n"); +#endif + break; + } + // BA blocks * BS words (word = 32-bits) + size = (bcr >> 16) * (bcr & 0xffff); + GPU_readDataMem(ptr, size); + psxCpu->Clear(madr, size); + +#if 1 + // already 32-bit word size ((size * 4) / 4) + GPUDMA_INT(size); +#else + // Experimental burst dma transfer (0.333x max) + GPUDMA_INT(size/3); +#endif + return; + + case 0x01000201: // mem2vram +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + ptr = (u32 *)PSXM(madr); + if (ptr == NULL) { +#ifdef CPU_LOG + CPU_LOG("*** DMA2 GPU - mem2vram *** NULL Pointer!!!\n"); +#endif + break; + } + // BA blocks * BS words (word = 32-bits) + size = (bcr >> 16) * (bcr & 0xffff); + GPU_writeDataMem(ptr, size); + +#if 1 + // already 32-bit word size ((size * 4) / 4) + GPUDMA_INT(size); +#else + // Experimental burst dma transfer + // - X-Files = 0.333333x max for videos + GPUDMA_INT( size / 3 ); +#endif + return; + + case 0x01000401: // dma chain +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + size = gpuDmaChainSize(madr); + GPU_dmaChain((u32 *)psxM, madr & 0x1fffff); + + // Tekken 3 = use 1.0 only (not 1.5x) + + // Einhander = parse linked list in pieces (todo) + // Final Fantasy 4 = internal vram time (todo) + // Rebel Assault 2 = parse linked list in pieces (todo) + // Vampire Hunter D = allow edits to linked list (todo) + GPUDMA_INT(size); + return; + +#ifdef PSXDMA_LOG + default: + PSXDMA_LOG("*** DMA 2 - GPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; +#endif + } + + HW_DMA2_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(2); +} + +void gpuInterrupt() { + HW_DMA2_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(2); +} diff --git a/libpcsxcore/gpu.h b/libpcsxcore/gpu.h index fd02701d..e3be65a1 100644..100755 --- a/libpcsxcore/gpu.h +++ b/libpcsxcore/gpu.h @@ -1,18 +1,18 @@ -#ifndef __GPU_H__
-#define __GPU_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-int gpuReadStatus();
-
-void psxDma2(u32 madr, u32 bcr, u32 chcr);
-void gpuInterrupt();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#ifndef __GPU_H__ +#define __GPU_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +int gpuReadStatus(); + +void psxDma2(u32 madr, u32 bcr, u32 chcr); +void gpuInterrupt(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libpcsxcore/ix86/iR3000A.c b/libpcsxcore/ix86/iR3000A.c index 029b8bab..942429b2 100644..100755 --- a/libpcsxcore/ix86/iR3000A.c +++ b/libpcsxcore/ix86/iR3000A.c @@ -1,3015 +1,3015 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* i386 assembly functions for R3000A core.
-*/
-
-#ifdef __i386__
-
-#include "ix86.h"
-#include <sys/mman.h>
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-u32 *psxRecLUT;
-
-#undef PC_REC
-#undef PC_REC8
-#undef PC_REC16
-#undef PC_REC32
-#define PC_REC(x) (psxRecLUT[(x) >> 16] + ((x) & 0xffff))
-#define PC_REC8(x) (*(u8 *)PC_REC(x))
-#define PC_REC16(x) (*(u16*)PC_REC(x))
-#define PC_REC32(x) (*(u32*)PC_REC(x))
-
-#define RECMEM_SIZE (8 * 1024 * 1024)
-
-static char *recMem; /* the recompiled blocks will be here */
-static char *recRAM; /* and the ptr to the blocks here */
-static char *recROM; /* and here */
-
-static u32 pc; /* recompiler pc */
-static u32 pcold; /* recompiler oldpc */
-static int count; /* recompiler intruction count */
-static int branch; /* set for branch */
-static u32 target; /* branch target */
-static u32 resp;
-
-typedef struct {
- int state;
- u32 k;
- int reg;
-} iRegisters;
-
-static iRegisters iRegs[32];
-static iRegisters iRegsS[32];
-
-#define ST_UNK 0
-#define ST_CONST 1
-#define ST_MAPPED 2
-
-#define IsConst(reg) (iRegs[reg].state == ST_CONST)
-#define IsMapped(reg) (iRegs[reg].state == ST_MAPPED)
-
-static void (*recBSC[64])();
-static void (*recSPC[64])();
-static void (*recREG[32])();
-static void (*recCP0[32])();
-static void (*recCP2[64])();
-static void (*recCP2BSC[32])();
-
-#define DYNAREC_BLOCK 50
-
-static void MapConst(int reg, u32 _const) {
- iRegs[reg].k = _const;
- iRegs[reg].state = ST_CONST;
-}
-
-static void iFlushReg(int reg) {
- if (IsConst(reg)) {
- MOV32ItoM((u32)&psxRegs.GPR.r[reg], iRegs[reg].k);
- }
- iRegs[reg].state = ST_UNK;
-}
-
-static void iFlushRegs() {
- int i;
-
- for (i=1; i<32; i++) {
- iFlushReg(i);
- }
-}
-
-static void iRet() {
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((u32)&psxRegs.cycle, count);
- if (resp) ADD32ItoR(ESP, resp);
- RET();
-}
-
-static int iLoadTest() {
- u32 tmp;
-
- // check for load delay
- tmp = psxRegs.code >> 26;
- switch (tmp) {
- case 0x10: // COP0
- switch (_Rs_) {
- case 0x00: // MFC0
- case 0x02: // CFC0
- return 1;
- }
- break;
- case 0x12: // COP2
- switch (_Funct_) {
- case 0x00:
- switch (_Rs_) {
- case 0x00: // MFC2
- case 0x02: // CFC2
- return 1;
- }
- break;
- }
- break;
- case 0x32: // LWC2
- return 1;
- default:
- if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
- return 1;
- }
- break;
- }
- return 0;
-}
-
-/* set a pending branch */
-static void SetBranch() {
- branch = 1;
- psxRegs.code = PSXMu32(pc);
- pc += 4;
-
- if (iLoadTest() == 1) {
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.code, psxRegs.code);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((u32)&psxRegs.cycle, count);
- if (resp) ADD32ItoR(ESP, resp);
-
- PUSH32M((u32)&target);
- PUSH32I(_Rt_);
- CALLFunc((u32)psxDelayTest);
- ADD32ItoR(ESP, 2*4);
-
- RET();
- return;
- }
- switch( psxRegs.code >> 26 ) {
- // Lode Runner (jr - beq)
-
- // bltz - bgez - bltzal - bgezal / beq - bne - blez - bgtz
- case 0x01:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- break;
-
- default:
- recBSC[psxRegs.code>>26]();
- break;
- }
-
- iFlushRegs();
- MOV32MtoR(EAX, (u32)&target);
- MOV32RtoM((u32)&psxRegs.pc, EAX);
- CALLFunc((u32)psxBranchTest);
-
- iRet();
-}
-
-static void iJump(u32 branchPC) {
- branch = 1;
- psxRegs.code = PSXMu32(pc);
- pc+=4;
-
- if (iLoadTest() == 1) {
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.code, psxRegs.code);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((u32)&psxRegs.cycle, count);
- if (resp) ADD32ItoR(ESP, resp);
-
- PUSH32I(branchPC);
- PUSH32I(_Rt_);
- CALLFunc((u32)psxDelayTest);
- ADD32ItoR(ESP, 2*4);
-
- RET();
- return;
- }
-
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.pc, branchPC);
- CALLFunc((u32)psxBranchTest);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((u32)&psxRegs.cycle, count);
- if (resp) ADD32ItoR(ESP, resp);
-
- // maybe just happened an interruption, check so
- CMP32ItoM((u32)&psxRegs.pc, branchPC);
- j8Ptr[0] = JE8(0);
- RET();
-
- x86SetJ8(j8Ptr[0]);
- MOV32MtoR(EAX, PC_REC(branchPC));
- TEST32RtoR(EAX, EAX);
- j8Ptr[1] = JNE8(0);
- RET();
-
- x86SetJ8(j8Ptr[1]);
- RET();
- JMP32R(EAX);
-}
-
-static void iBranch(u32 branchPC, int savectx) {
- u32 respold=0;
-
- if (savectx) {
- respold = resp;
- memcpy(iRegsS, iRegs, sizeof(iRegs));
- }
-
- branch = 1;
- psxRegs.code = PSXMu32(pc);
-
- // the delay test is only made when the branch is taken
- // savectx == 0 will mean that :)
- if (savectx == 0 && iLoadTest() == 1) {
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.code, psxRegs.code);
- /* store cycle */
- count = (((pc+4) - pcold) / 4) * BIAS;
- ADD32ItoM((u32)&psxRegs.cycle, count);
- if (resp) ADD32ItoR(ESP, resp);
-
- PUSH32I(branchPC);
- PUSH32I(_Rt_);
- CALLFunc((u32)psxDelayTest);
- ADD32ItoR(ESP, 2*4);
-
- RET();
- return;
- }
-
- pc+= 4;
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.pc, branchPC);
- CALLFunc((u32)psxBranchTest);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((u32)&psxRegs.cycle, count);
- if (resp) ADD32ItoR(ESP, resp);
-
- // maybe just happened an interruption, check so
- CMP32ItoM((u32)&psxRegs.pc, branchPC);
- j8Ptr[1] = JE8(0);
- RET();
-
- x86SetJ8(j8Ptr[1]);
- MOV32MtoR(EAX, PC_REC(branchPC));
- TEST32RtoR(EAX, EAX);
- j8Ptr[2] = JNE8(0);
- RET();
-
- x86SetJ8(j8Ptr[2]);
- JMP32R(EAX);
-
- pc-= 4;
- if (savectx) {
- resp = respold;
- memcpy(iRegs, iRegsS, sizeof(iRegs));
- }
-}
-
-
-char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n";
-char *txt1 = "EAX = %x\n";
-char *txt2 = "M32 = %x\n";
-
-void iLogX86() {
- PUSHA32();
-
- PUSH32R (EDX);
- PUSH32R (ECX);
- PUSH32R (EAX);
- PUSH32M ((u32)&txt0);
- CALLFunc ((u32)SysPrintf);
- ADD32ItoR(ESP, 4*4);
-
- POPA32();
-}
-
-void iLogEAX() {
- PUSH32R (EAX);
- PUSH32M ((u32)&txt1);
- CALLFunc ((u32)SysPrintf);
- ADD32ItoR(ESP, 4*2);
-}
-
-void iLogM32(u32 mem) {
- PUSH32M (mem);
- PUSH32M ((u32)&txt2);
- CALLFunc ((u32)SysPrintf);
- ADD32ItoR(ESP, 4*2);
-}
-
-#if 0
-static void iDumpRegs() {
- int i, j;
-
- printf("%x %x\n", psxRegs.pc, psxRegs.cycle);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 8; j++)
- printf("%x ", psxRegs.GPR.r[j * i]);
- printf("\n");
- }
-}
-#endif
-
-void iDumpBlock(char *ptr) {
- FILE *f;
- u32 i;
-
- SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle);
-
- for (i = psxRegs.pc; i < pc; i += 4)
- SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
-
- fflush(stdout);
- f = fopen("dump1", "w");
- fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f);
- fclose(f);
- system("ndisasmw -u dump1");
- fflush(stdout);
-}
-
-#define REC_FUNC(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(); \
- MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
- MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
- CALLFunc((u32)psx##f); \
-/* branch = 2; */\
-}
-
-#define REC_SYS(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(); \
- MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
- MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
- CALLFunc((u32)psx##f); \
- branch = 2; \
- iRet(); \
-}
-
-#define REC_BRANCH(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(); \
- MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
- MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
- CALLFunc((u32)psx##f); \
- branch = 2; \
- iRet(); \
-}
-
-static void recRecompile();
-
-static int recInit() {
- int i;
-
- psxRecLUT = (u32 *)malloc(0x010000 * 4);
-
- recMem = mmap(0, RECMEM_SIZE + 0x1000,
- PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- recRAM = (char *)malloc(0x200000);
- recROM = (char *)malloc(0x080000);
- if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) {
- SysMessage("Error allocating memory"); return -1;
- }
-
- for (i = 0; i < 0x80; i++) psxRecLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16];
- memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * 4);
- memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * 4);
-
- for (i = 0; i < 0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16];
-
- return 0;
-}
-
-static void recReset() {
- memset(recRAM, 0, 0x200000);
- memset(recROM, 0, 0x080000);
-
- x86Init();
-
- x86SetPtr(recMem);
-
- branch = 0;
- memset(iRegs, 0, sizeof(iRegs));
- iRegs[0].state = ST_CONST;
- iRegs[0].k = 0;
-}
-
-static void recShutdown() {
- if (recMem == NULL) return;
- free(psxRecLUT);
- munmap(recMem, RECMEM_SIZE + 0x1000);
- free(recRAM);
- free(recROM);
- x86Shutdown();
-}
-
-static void recError() {
- SysReset();
- ClosePlugins();
- SysMessage("Unrecoverable error while running recompiler\n");
- SysRunGui();
-}
-
-__inline static void execute() {
- void (**recFunc)() = NULL;
- char *p;
-
- p = (char *)PC_REC(psxRegs.pc);
- if (p != NULL) recFunc = (void (**)()) (u32)p;
- else { recError(); return; }
-
- if (*recFunc == 0) {
- recRecompile();
- }
- (*recFunc)();
-}
-
-static void recExecute() {
- for (;;) execute();
-}
-
-static void recExecuteBlock() {
- execute();
-}
-
-static void recClear(u32 Addr, u32 Size) {
- u32 bank,offset;
-
- bank = Addr >> 24;
- offset = Addr & 0xffffff;
-
-
- // Pitfall 3D - clear dynarec slots that contain 'stale' ram data
- // - fixes stage 1 loading crash
- if( bank == 0x80 || bank == 0xa0 || bank == 0x00 ) {
- offset &= 0x1fffff;
-
- if( offset >= DYNAREC_BLOCK * 4 )
- memset((void*)PC_REC(Addr - DYNAREC_BLOCK * 4), 0, DYNAREC_BLOCK * 4);
- else
- memset((void*)PC_REC(Addr - offset), 0, offset);
- }
-
-
- memset((void*)PC_REC(Addr), 0, Size * 4);
-}
-
-static void recNULL() {
-// SysMessage("recUNK: %8.8x\n", psxRegs.code);
-}
-
-/*********************************************************
-* goes to opcodes tables... *
-* Format: table[something....] *
-*********************************************************/
-
-//REC_SYS(SPECIAL);
-static void recSPECIAL() {
- recSPC[_Funct_]();
-}
-
-static void recREGIMM() {
- recREG[_Rt_]();
-}
-
-static void recCOP0() {
- recCP0[_Rs_]();
-}
-
-//REC_SYS(COP2);
-static void recCOP2() {
- MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
- AND32ItoR(EAX, 0x40000000);
- j8Ptr[31] = JZ8(0);
-
- recCP2[_Funct_]();
-
- x86SetJ8(j8Ptr[31]);
-}
-
-static void recBASIC() {
- recCP2BSC[_Rs_]();
-}
-
-//end of Tables opcodes...
-
-/*********************************************************
-* Arithmetic with immediate operand *
-* Format: OP rt, rs, immediate *
-*********************************************************/
-
-/*REC_FUNC(ADDI);
-REC_FUNC(ADDIU);
-REC_FUNC(ANDI);
-REC_FUNC(ORI);
-REC_FUNC(XORI);
-REC_FUNC(SLTI);
-REC_FUNC(SLTIU);
-#if 0*/
-static void recADDIU() {
-// Rt = Rs + Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k+= _Imm_;
- } else {
- if (_Imm_ == 1) {
- INC32M((u32)&psxRegs.GPR.r[_Rt_]);
- } else if (_Imm_ == -1) {
- DEC32M((u32)&psxRegs.GPR.r[_Rt_]);
- } else if (_Imm_) {
- ADD32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_);
- }
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_ == 1) {
- INC32R(EAX);
- } else if (_Imm_ == -1) {
- DEC32R(EAX);
- } else if (_Imm_) {
- ADD32ItoR(EAX, _Imm_);
- }
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-
-static void recADDI() {
-// Rt = Rs + Im
- recADDIU();
-}
-
-static void recSLTI() {
-// Rt = Rs < Im (signed)
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, _Imm_);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-}
-
-static void recSLTIU() {
-// Rt = Rs < Im (unsigned)
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, _Imm_);
- SETB8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-}
-
-static void recANDI() {
-// Rt = Rs And Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k&= _ImmU_;
- } else {
- AND32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- AND32ItoR(EAX, _ImmU_);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-
-static void recORI() {
-// Rt = Rs Or Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k|= _ImmU_;
- } else {
- OR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_ImmU_) OR32ItoR (EAX, _ImmU_);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-
-static void recXORI() {
-// Rt = Rs Xor Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k^= _ImmU_;
- } else {
- XOR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- XOR32ItoR(EAX, _ImmU_);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-//#endif
-//end of * Arithmetic with immediate operand
-
-/*********************************************************
-* Load higher 16 bits of the first word in GPR with imm *
-* Format: OP rt, immediate *
-*********************************************************/
-/*REC_FUNC(LUI);
-#if 0*/
-static void recLUI() {
-// Rt = Imm << 16
- if (!_Rt_) return;
-
- MapConst(_Rt_, psxRegs.code << 16);
-}
-//#endif
-//End of Load Higher .....
-
-
-/*********************************************************
-* Register arithmetic *
-* Format: OP rd, rs, rt *
-*********************************************************/
-
-/*REC_FUNC(ADD);
-REC_FUNC(ADDU);
-REC_FUNC(SUB);
-REC_FUNC(SUBU);
-REC_FUNC(AND);
-REC_FUNC(OR);
-REC_FUNC(XOR);
-REC_FUNC(NOR);
-REC_FUNC(SLT);
-REC_FUNC(SLTU);
-
-#if 0*/
-static void recADDU() {
-// Rd = Rs + Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rt_ == _Rd_) {
- if (iRegs[_Rs_].k == 1) {
- INC32M((u32)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rs_].k == -1) {
- DEC32M((u32)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rs_].k) {
- ADD32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
- }
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- if (iRegs[_Rs_].k == 1) {
- INC32R(EAX);
- } else if (iRegs[_Rs_].k == 0xffffffff) {
- DEC32R(EAX);
- } else if (iRegs[_Rs_].k) {
- ADD32ItoR(EAX, iRegs[_Rs_].k);
- }
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rs_ == _Rd_) {
- if (iRegs[_Rt_].k == 1) {
- INC32M((u32)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rt_].k == -1) {
- DEC32M((u32)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rt_].k) {
- ADD32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
- }
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (iRegs[_Rt_].k == 1) {
- INC32R(EAX);
- } else if (iRegs[_Rt_].k == 0xffffffff) {
- DEC32R(EAX);
- } else if (iRegs[_Rt_].k) {
- ADD32ItoR(EAX, iRegs[_Rt_].k);
- }
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rs_ == _Rd_) { // Rd+= Rt
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- ADD32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (_Rt_ == _Rd_) { // Rd+= Rs
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- ADD32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else { // Rd = Rs + Rt
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- ADD32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
- }
-}
-
-static void recADD() {
-// Rd = Rs + Rt
- recADDU();
-}
-
-static void recSUBU() {
-// Rd = Rs - Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- SUB32ItoR(EAX, iRegs[_Rt_].k);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSUB() {
-// Rd = Rs - Rt
- recSUBU();
-}
-
-static void recAND() {
-// Rd = Rs And Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rd_ == _Rt_) { // Rd&= Rs
- AND32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
- } else {
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rd_ == _Rs_) { // Rd&= kRt
- AND32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
- } else { // Rd = Rs & kRt
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- AND32ItoR(EAX, iRegs[_Rt_].k);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rs_ == _Rd_) { // Rd&= Rt
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- AND32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (_Rt_ == _Rd_) { // Rd&= Rs
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- AND32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else { // Rd = Rs & Rt
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
- }
-}
-
-static void recOR() {
-// Rd = Rs Or Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- OR32ItoR (EAX, iRegs[_Rt_].k);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recXOR() {
-// Rd = Rs Xor Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- XOR32ItoR(EAX, iRegs[_Rt_].k);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recNOR() {
-// Rd = Rs Nor Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k));
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- NOT32R (EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- OR32ItoR (EAX, iRegs[_Rt_].k);
- NOT32R (EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- NOT32R (EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSLT() {
-// Rd = Rs < Rt (signed)
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, iRegs[_Rt_].k);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSLTU() {
-// Rd = Rs < Rt (unsigned)
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- SBB32RtoR(EAX, EAX);
- NEG32R (EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, iRegs[_Rt_].k);
- SBB32RtoR(EAX, EAX);
- NEG32R (EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- SBB32RtoR(EAX, EAX);
- NEG32R (EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-//#endif
-//End of * Register arithmetic
-
-/*********************************************************
-* Register mult/div & Register trap logic *
-* Format: OP rs, rt *
-*********************************************************/
-
-/*REC_FUNC(MULT);
-REC_FUNC(MULTU);
-REC_FUNC(DIV);
-REC_FUNC(DIVU);
-#if 0*/
-static void recMULT() {
-// Lo/Hi = Rs * Rt (signed)
-
-// iFlushRegs();
-
- if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
- (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
- XOR32RtoR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- return;
- }
-
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- }
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k);
- IMUL32R (EDX);
- } else {
- IMUL32M ((u32)&psxRegs.GPR.r[_Rt_]);
- }
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
-}
-
-static void recMULTU() {
-// Lo/Hi = Rs * Rt (unsigned)
-
-// iFlushRegs();
-
- if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
- (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
- XOR32RtoR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- return;
- }
-
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- }
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k);
- MUL32R (EDX);
- } else {
- MUL32M ((u32)&psxRegs.GPR.r[_Rt_]);
- }
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
-}
-
-static void recDIV() {
-// Lo/Hi = Rs / Rt (signed)
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- if (iRegs[_Rt_].k == 0) {
- MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- }
- return;
- }
- MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- CMP32ItoR(ECX, 0);
- j8Ptr[0] = JE8(0);
- }
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- }
- CDQ();
- IDIV32R (ECX);
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
-
- if (!IsConst(_Rt_)) {
- j8Ptr[1] = JMP8(1);
-
- x86SetJ8(j8Ptr[0]);
-
- MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- }
-
- x86SetJ8(j8Ptr[1]);
- }
-}
-
-static void recDIVU() {
-// Lo/Hi = Rs / Rt (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- if (iRegs[_Rt_].k == 0) {
- MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- }
- return;
- }
- MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- CMP32ItoR(ECX, 0);
- j8Ptr[0] = JE8(0);
- }
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- }
- XOR32RtoR(EDX, EDX);
- DIV32R (ECX);
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
-
- if (!IsConst(_Rt_)) {
- j8Ptr[1] = JMP8(1);
-
- x86SetJ8(j8Ptr[0]);
-
- MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- }
-
- x86SetJ8(j8Ptr[1]);
- }
-}
-//#endif
-//End of * Register mult/div & Register trap logic
-
-/*REC_FUNC(LB);
-REC_FUNC(LBU);
-REC_FUNC(LH);
-REC_FUNC(LHU);
-REC_FUNC(LW);
-
-REC_FUNC(SB);
-REC_FUNC(SH);
-REC_FUNC(SW);*/
-
-//REC_FUNC(LWL);
-//REC_FUNC(LWR);
-//REC_FUNC(SWL);
-//REC_FUNC(SWR);
-
-/* Push OfB for Stores/Loads */
-static void iPushOfB() {
- if (IsConst(_Rs_)) {
- PUSH32I (iRegs[_Rs_].k + _Imm_);
- } else {
- if (_Imm_) {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- ADD32ItoR(EAX, _Imm_);
- PUSH32R (EAX);
- } else {
- PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]);
- }
- }
-}
-
-//#if 0
-static void recLB() {
-// Rt = mem[Rs + Im] (signed)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRs8(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M8toR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
-// SysPrintf("unhandled r8 %x\n", addr);
- }
-
- iPushOfB();
- CALLFunc((u32)psxMemRead8);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVSX32R8toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-}
-
-static void recLBU() {
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu8(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M8toR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
-// SysPrintf("unhandled r8u %x\n", addr);
- }
-
- iPushOfB();
- CALLFunc((u32)psxMemRead8);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVZX32R8toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-}
-
-static void recLH() {
-// Rt = mem[Rs + Im] (signed)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRs16(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M16toR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
-// SysPrintf("unhandled r16 %x\n", addr);
- }
-
- iPushOfB();
- CALLFunc((u32)psxMemRead16);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVSX32R16toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-}
-
-static void recLHU() {
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu16(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M16toR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80) {
- if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- PUSH32I (addr);
- CALL32M ((u32)&SPU_readRegister);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
-#ifndef __WIN32__
- resp+= 4;
-#endif
- return;
- }
- switch (addr) {
- case 0x1f801100: case 0x1f801110: case 0x1f801120:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- PUSH32I((addr >> 4) & 0x3);
- CALLFunc((u32)psxRcntRcount);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- resp+= 4;
- return;
-
- case 0x1f801104: case 0x1f801114: case 0x1f801124:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- PUSH32I((addr >> 4) & 0x3);
- CALLFunc((u32)psxRcntRmode);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- resp+= 4;
- return;
-
- case 0x1f801108: case 0x1f801118: case 0x1f801128:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- PUSH32I((addr >> 4) & 0x3);
- CALLFunc((u32)psxRcntRtarget);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- resp+= 4;
- return;
- }
- }
-// SysPrintf("unhandled r16u %x\n", addr);
- }
-
- iPushOfB();
- CALLFunc((u32)psxMemRead16);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-}
-
-static void recLW() {
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu32(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80) {
- switch (addr) {
- case 0x1f801080: case 0x1f801084: case 0x1f801088:
- case 0x1f801090: case 0x1f801094: case 0x1f801098:
- case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8:
- case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8:
- case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8:
- case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8:
- case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8:
- case 0x1f801070: case 0x1f801074:
- case 0x1f8010f0: case 0x1f8010f4:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
-
- case 0x1f801810:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- CALL32M((u32)&GPU_readData);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
-
- case 0x1f801814:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- CALL32M((u32)&GPU_readStatus);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-// SysPrintf("unhandled r32 %x\n", addr);
- }
-
- iPushOfB();
- CALLFunc((u32)psxMemRead32);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-}
-
-extern u32 LWL_MASK[4];
-extern u32 LWL_SHIFT[4];
-
-void iLWLk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32ItoR(ECX, LWL_MASK[shift]);
- SHL32ItoR(EAX, LWL_SHIFT[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recLWL() {
-// Rt = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iLWLk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iLWLk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
- CALLFunc((u32)psxMemRead32);
-
- if (_Rt_) {
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)LWL_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
-
- MOV32ItoR(ECX, (u32)LWL_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
-
- OR32RtoR(EAX, EDX);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- } else {
-// ADD32ItoR(ESP, 8);
- resp+= 8;
- }
-}
-
-#if 0
-static void recLWBlock(int count) {
- u32 *code = (u32 *)PSXM(pc);
- int i, respsave;
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- // since bios is readonly it won't change
- for (i = 0; i < count; i++, code++, addr += 4) {
- if (_fRt_(*code)) {
- MapConst(_fRt_(*code), psxRu32(addr));
- }
- }
- return;
- }
- if ((t & 0x1fe0) == 0) {
- for (i = 0; i < count; i++, code++, addr += 4) {
- if (!_fRt_(*code))
- return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- for (i = 0; i < count; i++, code++, addr += 4) {
- if (!_fRt_(*code))
- return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- }
-
- SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
- iPushOfB();
- CALLFunc((u32)psxMemPointer);
-// ADD32ItoR(ESP, 4);
- resp += 4;
-
- respsave = resp; resp = 0;
- TEST32RtoR(EAX, EAX);
- j32Ptr[4] = JZ32(0);
- XOR32RtoR(ECX, ECX);
- for (i = 0; i < count; i++, code++) {
- if (_fRt_(*code)) {
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32RmStoR(EDX, EAX, ECX, 2);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX);
- }
- if (i != (count - 1))
- INC32R(ECX);
- }
- j32Ptr[5] = JMP32(0);
- x86SetJ32(j32Ptr[4]);
- for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) {
- psxRegs.code = *code;
- recLW();
- }
- ADD32ItoR(ESP, resp);
- x86SetJ32(j32Ptr[5]);
- resp = respsave;
-}
-#endif
-
-extern u32 LWR_MASK[4];
-extern u32 LWR_SHIFT[4];
-
-void iLWRk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32ItoR(ECX, LWR_MASK[shift]);
- SHR32ItoR(EAX, LWR_SHIFT[shift]);
- OR32RtoR(EAX, ECX);
-}
-
-void recLWR() {
-// Rt = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iLWRk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iLWRk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_))
- MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
- CALLFunc((u32)psxMemRead32);
-
- if (_Rt_) {
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)LWR_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
-
- MOV32ItoR(ECX, (u32)LWR_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
-
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
-
- OR32RtoR(EAX, EDX);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- } else {
-// ADD32ItoR(ESP, 8);
- resp+= 8;
- }
-}
-
-static void recSB() {
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
- } else {
- MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
-
- PUSH32I(1);
- PUSH32I(addr & ~3);
- CALLFunc((u32)&recClear);
- resp += 8;
- return;
- }
-
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
- } else {
- MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV8RtoM((u32)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
-// SysPrintf("unhandled w8 %x\n", addr);
- }
-
- if (IsConst(_Rt_)) {
- PUSH32I (iRegs[_Rt_].k);
- } else {
- PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
- }
- iPushOfB();
- CALLFunc((u32)psxMemWrite8);
-// ADD32ItoR(ESP, 8);
- resp+= 8;
-}
-
-static void recSH() {
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
- } else {
- MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
-
- PUSH32I(1);
- PUSH32I(addr & ~3);
- CALLFunc((u32)&recClear);
- resp += 8;
- return;
- }
-
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
- } else {
- MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV16RtoM((u32)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
- if (t == 0x1f80) {
- if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
- if (IsConst(_Rt_)) {
- PUSH32I(iRegs[_Rt_].k);
- } else {
- PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
- }
- PUSH32I (addr);
- CALL32M ((u32)&SPU_writeRegister);
-#ifndef __WIN32__
- resp+= 8;
-#endif
- return;
- }
- }
-// SysPrintf("unhandled w16 %x\n", addr);
- }
-
- if (IsConst(_Rt_)) {
- PUSH32I (iRegs[_Rt_].k);
- } else {
- PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
- }
- iPushOfB();
- CALLFunc((u32)psxMemWrite16);
-// ADD32ItoR(ESP, 8);
- resp+= 8;
-}
-
-static void recSW() {
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
-
- PUSH32I(1);
- PUSH32I(addr);
- CALLFunc((u32)&recClear);
- resp += 8;
- return;
- }
-
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV32ItoM((u32)&psxH[addr & 0xfff], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
- if (t == 0x1f80) {
- switch (addr) {
- case 0x1f801080: case 0x1f801084:
- case 0x1f801090: case 0x1f801094:
- case 0x1f8010a0: case 0x1f8010a4:
- case 0x1f8010b0: case 0x1f8010b4:
- case 0x1f8010c0: case 0x1f8010c4:
- case 0x1f8010d0: case 0x1f8010d4:
- case 0x1f8010e0: case 0x1f8010e4:
- case 0x1f801074:
- case 0x1f8010f0:
- if (IsConst(_Rt_)) {
- MOV32ItoM((u32)&psxH[addr & 0xffff], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((u32)&psxH[addr & 0xffff], EAX);
- }
- return;
-
- case 0x1f801810:
- if (IsConst(_Rt_)) {
- PUSH32I(iRegs[_Rt_].k);
- } else {
- PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
- }
- CALL32M((u32)&GPU_writeData);
-#ifndef __WIN32__
- resp+= 4;
-#endif
- return;
-
- case 0x1f801814:
- if (IsConst(_Rt_)) {
- PUSH32I(iRegs[_Rt_].k);
- } else {
- PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
- }
- CALL32M((u32)&GPU_writeStatus);
-#ifndef __WIN32__
- resp+= 4;
-#endif
- return;
- }
- }
-// SysPrintf("unhandled w32 %x\n", addr);
- }
-
- if (IsConst(_Rt_)) {
- PUSH32I (iRegs[_Rt_].k);
- } else {
- PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
- }
- iPushOfB();
- CALLFunc((u32)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- resp+= 8;
-}
-//#endif
-
-#if 0
-static void recSWBlock(int count) {
- u32 *code;
- int i, respsave;
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
- code = (u32 *)PSXM(pc);
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- for (i = 0; i < count; i++, code++, addr += 4) {
- if (IsConst(_fRt_(*code))) {
- MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
- MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- for (i = 0; i < count; i++, code++, addr += 4) {
- if (!_fRt_(*code))
- return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- }
-
- SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
- iPushOfB();
- CALLFunc((u32)psxMemPointer);
-// ADD32ItoR(ESP, 4);
- resp += 4;
-
- respsave = resp;
- resp = 0;
- TEST32RtoR(EAX, EAX);
- j32Ptr[4] = JZ32(0);
- XOR32RtoR(ECX, ECX);
- for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) {
- if (IsConst(_fRt_(*code))) {
- MOV32ItoR(EDX, iRegs[_fRt_(*code)].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
- }
- MOV32RtoRmS(EAX, ECX, 2, EDX);
- if (i != (count - 1))
- INC32R(ECX);
- }
- j32Ptr[5] = JMP32(0);
- x86SetJ32(j32Ptr[4]);
- for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) {
- psxRegs.code = *code;
- recSW();
- }
- ADD32ItoR(ESP, resp);
- x86SetJ32(j32Ptr[5]);
- resp = respsave;
-}
-#endif
-
-extern u32 SWL_MASK[4];
-extern u32 SWL_SHIFT[4];
-
-void iSWLk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHR32ItoR(ECX, SWL_SHIFT[shift]);
- AND32ItoR(EAX, SWL_MASK[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recSWL() {
-// mem[Rs + Im] = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
-#if 0
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iSWLk(addr & 3);
- MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
- return;
- }
-#endif
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iSWLk(addr & 3);
- MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemRead32);
-
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)SWL_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
-
- MOV32ItoR(ECX, (u32)SWL_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
-
- OR32RtoR (EAX, EDX);
- PUSH32R (EAX);
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- resp+= 8;
-}
-
-extern u32 SWR_MASK[4];
-extern u32 SWR_SHIFT[4];
-
-void iSWRk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHL32ItoR(ECX, SWR_SHIFT[shift]);
- AND32ItoR(EAX, SWR_MASK[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recSWR() {
-// mem[Rs + Im] = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
-#if 0
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iSWRk(addr & 3);
- MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
- return;
- }
-#endif
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iSWRk(addr & 3);
- MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemRead32);
-
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)SWR_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
-
- MOV32ItoR(ECX, (u32)SWR_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
-
- OR32RtoR (EAX, EDX);
- PUSH32R (EAX);
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- resp += 8;
-}
-
-/*REC_FUNC(SLL);
-REC_FUNC(SRL);
-REC_FUNC(SRA);
-#if 0*/
-static void recSLL() {
-// Rd = Rt << Sa
- if (!_Rd_)
- return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- if (_Sa_) SHL32ItoR(EAX, _Sa_);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRL() {
-// Rd = Rt >> Sa
- if (!_Rd_)
- return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- if (_Sa_) SHR32ItoR(EAX, _Sa_);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRA() {
-// Rd = Rt >> Sa
- if (!_Rd_)
- return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- if (_Sa_) SAR32ItoR(EAX, _Sa_);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-//#endif
-
-/*REC_FUNC(SLLV);
-REC_FUNC(SRLV);
-REC_FUNC(SRAV);
-#if 0*/
-static void recSLLV() {
-// Rd = Rt << Rs
- if (!_Rd_)
- return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32ItoR(ECX, iRegs[_Rs_].k);
- SHL32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rt_].k);
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
- SHL32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
- SHL32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRLV() {
-// Rd = Rt >> Rs
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32ItoR(ECX, iRegs[_Rs_].k);
- SHR32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rt_].k);
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
- SHR32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
- SHR32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRAV() {
-// Rd = Rt >> Rs
- if (!_Rd_)
- return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32ItoR(ECX, iRegs[_Rs_].k);
- SAR32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rt_].k);
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
- SAR32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
- SAR32CLtoR(EAX);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-//#endif
-
-/*REC_SYS(SYSCALL);
-REC_SYS(BREAK);
-
-#if 0*/
-int dump;
-static void recSYSCALL() {
-// dump = 1;
- iFlushRegs();
-
- MOV32ItoR(EAX, pc - 4);
- MOV32RtoM((u32)&psxRegs.pc, EAX);
- PUSH32I (branch == 1 ? 1 : 0);
- PUSH32I (0x20);
- CALLFunc ((u32)psxException);
- ADD32ItoR(ESP, 8);
-
- branch = 2;
- iRet();
-}
-
-static void recBREAK() {
-}
-//#endif
-
-/*REC_FUNC(MFHI);
-REC_FUNC(MTHI);
-REC_FUNC(MFLO);
-REC_FUNC(MTLO);
-#if 0*/
-static void recMFHI() {
-// Rd = Hi
- if (!_Rd_)
- return;
-
- iRegs[_Rd_].state = ST_UNK;
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.hi);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
-}
-
-static void recMTHI() {
-// Hi = Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
- }
-}
-
-static void recMFLO() {
-// Rd = Lo
- if (!_Rd_)
- return;
-
- iRegs[_Rd_].state = ST_UNK;
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.lo);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
-}
-
-static void recMTLO() {
-// Lo = Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&psxRegs.GPR.n.lo, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
- }
-}
-//#endif
-
-/*REC_BRANCH(J);
-REC_BRANCH(JR);
-REC_BRANCH(JAL);
-REC_BRANCH(JALR);
-REC_BRANCH(BLTZ);
-REC_BRANCH(BGTZ);
-REC_BRANCH(BLTZAL);
-REC_BRANCH(BGEZAL);
-REC_BRANCH(BNE);
-REC_BRANCH(BEQ);
-REC_BRANCH(BLEZ);
-REC_BRANCH(BGEZ);*/
-
-//#if 0
-static void recBLTZ() {
-// Branch if Rs < 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
-
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k < 0) {
- iJump(bpc);
- return;
- } else {
- iJump(pc + 4);
- return;
- }
- }
-
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JL32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc += 4;
-}
-
-static void recBGTZ() {
-// Branch if Rs > 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k > 0) {
- iJump(bpc);
- return;
- } else {
- iJump(pc + 4);
- return;
- }
- }
-
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JG32(0);
-
- iBranch(pc + 4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBLTZAL() {
-// Branch if Rs < 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k < 0) {
- MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
- iJump(bpc); return;
- } else {
- iJump(pc + 4); return;
- }
- }
-
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JL32(0);
-
- iBranch(pc + 4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
- iBranch(bpc, 0);
- pc += 4;
-}
-
-static void recBGEZAL() {
-// Branch if Rs >= 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k >= 0) {
- MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JGE32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recJ() {
-// j target
-
- iJump(_Target_ * 4 + (pc & 0xf0000000));
-}
-
-static void recJAL() {
-// jal target
-
- MapConst(31, pc + 4);
-
- iJump(_Target_ * 4 + (pc & 0xf0000000));
-}
-
-static void recJR() {
-// jr Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&target, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&target, EAX);
- }
-
- SetBranch();
-}
-
-static void recJALR() {
-// jalr Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((u32)&target, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((u32)&target, EAX);
- }
-
- if (_Rd_) {
- MapConst(_Rd_, pc + 4);
- }
-
- SetBranch();
-}
-
-static void recBEQ() {
-// Branch if Rs == Rt
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (_Rs_ == _Rt_) {
- iJump(bpc);
- } else {
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
- iJump(bpc);
- return;
- } else {
- iJump(pc + 4);
- return;
- }
- } else if (IsConst(_Rs_)) {
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
- } else if (IsConst(_Rt_)) {
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
-
- j32Ptr[4] = JE32(0);
-
- iBranch(pc + 4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc += 4;
- }
-}
-
-static void recBNE() {
-// Branch if Rs != Rt
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
- iJump(bpc);
- return;
- } else {
- iJump(pc + 4);
- return;
- }
- } else if (IsConst(_Rs_)) {
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
- } else if (IsConst(_Rt_)) {
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- j32Ptr[4] = JNE32(0);
-
- iBranch(pc + 4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc += 4;
-}
-
-static void recBLEZ() {
-// Branch if Rs <= 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k <= 0) {
- iJump(bpc);
- return;
- } else {
- iJump(pc + 4);
- return;
- }
- }
-
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JLE32(0);
-
- iBranch(pc + 4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc += 4;
-}
-
-static void recBGEZ() {
-// Branch if Rs >= 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k >= 0) {
- iJump(bpc);
- return;
- } else {
- iJump(pc + 4);
- return;
- }
- }
-
- CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JGE32(0);
-
- iBranch(pc + 4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc += 4;
-}
-//#endif
-
-/*REC_FUNC(MFC0);
-REC_SYS(MTC0);
-REC_FUNC(CFC0);
-REC_SYS(CTC0);
-REC_FUNC(RFE);
-#if 0*/
-static void recMFC0() {
-// Rt = Cop0->Rd
- if (!_Rt_) return;
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32MtoR(EAX, (u32)&psxRegs.CP0.r[_Rd_]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
-}
-
-static void recCFC0() {
-// Rt = Cop0->Rd
-
- recMFC0();
-}
-
-void psxMTC0();
-static void recMTC0() {
-// Cop0->Rd = Rt
-
- if (IsConst(_Rt_)) {
- switch (_Rd_) {
- case 12:
- MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
- break;
- case 13:
- MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
- break;
- default:
- MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
- break;
- }
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- switch (_Rd_) {
- case 13:
- AND32ItoR(EAX, ~(0xfc00));
- break;
- }
- MOV32RtoM((u32)&psxRegs.CP0.r[_Rd_], EAX);
- }
-
- if (_Rd_ == 12 || _Rd_ == 13) {
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.pc, (u32)pc);
- CALLFunc((u32)psxTestSWInts);
- if (branch == 0) {
- branch = 2;
- iRet();
- }
- }
-}
-
-static void recCTC0() {
-// Cop0->Rd = Rt
-
- recMTC0();
-}
-
-static void recRFE() {
- MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
- MOV32RtoR(ECX, EAX);
- AND32ItoR(EAX, 0xfffffff0);
- AND32ItoR(ECX, 0x3c);
- SHR32ItoR(ECX, 2);
- OR32RtoR (EAX, ECX);
- MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX);
-
- iFlushRegs();
- MOV32ItoM((u32)&psxRegs.pc, (u32)pc);
- CALLFunc((u32)psxTestSWInts);
- if (branch == 0) {
- branch = 2;
- iRet();
- }
-}
-//#endif
-
-#include "iGte.h"
-
-//
-
-static void recHLE() {
- iFlushRegs();
-
- MOV32ItoR(EAX, (u32)psxHLEt[psxRegs.code & 0xffff]);
- CALL32R(EAX);
- branch = 2;
- iRet();
-}
-
-//
-
-static void (*recBSC[64])() = {
- recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
- recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI ,
- recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
- recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL,
- recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL,
- recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recSPC[64])() = {
- recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV,
- recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
- recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL,
- recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL,
- recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR ,
- recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL
-};
-
-static void (*recREG[32])() = {
- recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recCP0[32])() = {
- recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recCP2[64])() = {
- recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00
- recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08
- recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10
- recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18
- recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20
- recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28
- recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30
- recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38
-};
-
-static void (*recCP2BSC[32])() = {
- recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, 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
-};
-
-static void recRecompile() {
- char *p;
- char *ptr;
-
- dump = 0;
- resp = 0;
-
- /* if x86Ptr reached the mem limit reset whole mem */
- if (((u32)x86Ptr - (u32)recMem) >= (RECMEM_SIZE - 0x10000))
- recReset();
-
- x86Align(32);
- ptr = x86Ptr;
-
- PC_REC32(psxRegs.pc) = (u32)x86Ptr;
- pc = psxRegs.pc;
- pcold = pc;
-
- for (count = 0; count < DYNAREC_BLOCK;) {
- p = (char *)PSXM(pc);
- if (p == NULL) recError();
- psxRegs.code = *(u32 *)p;
-/*
- if ((psxRegs.code >> 26) == 0x23) { // LW
- int i;
- u32 code;
-
- for (i=1;; i++) {
- p = (char *)PSXM(pc+i*4);
- if (p == NULL) recError();
- code = *(u32 *)p;
-
- if ((code >> 26) != 0x23 ||
- _fRs_(code) != _Rs_ ||
- _fImm_(code) != (_Imm_+i*4))
- break;
- }
- if (i > 1) {
- recLWBlock(i);
- pc = pc + i*4; continue;
- }
- }
-
- if ((psxRegs.code >> 26) == 0x2b) { // SW
- int i;
- u32 code;
-
- for (i=1;; i++) {
- p = (char *)PSXM(pc+i*4);
- if (p == NULL) recError();
- code = *(u32 *)p;
-
- if ((code >> 26) != 0x2b ||
- _fRs_(code) != _Rs_ ||
- _fImm_(code) != (_Imm_+i*4))
- break;
- }
- if (i > 1) {
- recSWBlock(i);
- pc = pc + i*4; continue;
- }
- }*/
-
- pc += 4;
- count++;
- recBSC[psxRegs.code >> 26]();
-
- if (branch) {
- branch = 0;
- if (dump) iDumpBlock(ptr);
- return;
- }
- }
-
- iFlushRegs();
-
- MOV32ItoM((u32)&psxRegs.pc, pc);
-
- iRet();
-}
-
-R3000Acpu psxRec = {
- recInit,
- recReset,
- recExecute,
- recExecuteBlock,
- recClear,
- recShutdown
-};
-
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* i386 assembly functions for R3000A core. +*/ + +#ifdef __i386__ + +#include "ix86.h" +#include <sys/mman.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +u32 *psxRecLUT; + +#undef PC_REC +#undef PC_REC8 +#undef PC_REC16 +#undef PC_REC32 +#define PC_REC(x) (psxRecLUT[(x) >> 16] + ((x) & 0xffff)) +#define PC_REC8(x) (*(u8 *)PC_REC(x)) +#define PC_REC16(x) (*(u16*)PC_REC(x)) +#define PC_REC32(x) (*(u32*)PC_REC(x)) + +#define RECMEM_SIZE (8 * 1024 * 1024) + +static char *recMem; /* the recompiled blocks will be here */ +static char *recRAM; /* and the ptr to the blocks here */ +static char *recROM; /* and here */ + +static u32 pc; /* recompiler pc */ +static u32 pcold; /* recompiler oldpc */ +static int count; /* recompiler intruction count */ +static int branch; /* set for branch */ +static u32 target; /* branch target */ +static u32 resp; + +typedef struct { + int state; + u32 k; + int reg; +} iRegisters; + +static iRegisters iRegs[32]; +static iRegisters iRegsS[32]; + +#define ST_UNK 0 +#define ST_CONST 1 +#define ST_MAPPED 2 + +#define IsConst(reg) (iRegs[reg].state == ST_CONST) +#define IsMapped(reg) (iRegs[reg].state == ST_MAPPED) + +static void (*recBSC[64])(); +static void (*recSPC[64])(); +static void (*recREG[32])(); +static void (*recCP0[32])(); +static void (*recCP2[64])(); +static void (*recCP2BSC[32])(); + +#define DYNAREC_BLOCK 50 + +static void MapConst(int reg, u32 _const) { + iRegs[reg].k = _const; + iRegs[reg].state = ST_CONST; +} + +static void iFlushReg(int reg) { + if (IsConst(reg)) { + MOV32ItoM((u32)&psxRegs.GPR.r[reg], iRegs[reg].k); + } + iRegs[reg].state = ST_UNK; +} + +static void iFlushRegs() { + int i; + + for (i=1; i<32; i++) { + iFlushReg(i); + } +} + +static void iRet() { + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + RET(); +} + +static int iLoadTest() { + u32 tmp; + + // check for load delay + tmp = psxRegs.code >> 26; + switch (tmp) { + case 0x10: // COP0 + switch (_Rs_) { + case 0x00: // MFC0 + case 0x02: // CFC0 + return 1; + } + break; + case 0x12: // COP2 + switch (_Funct_) { + case 0x00: + switch (_Rs_) { + case 0x00: // MFC2 + case 0x02: // CFC2 + return 1; + } + break; + } + break; + case 0x32: // LWC2 + return 1; + default: + if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR + return 1; + } + break; + } + return 0; +} + +/* set a pending branch */ +static void SetBranch() { + branch = 1; + psxRegs.code = PSXMu32(pc); + pc += 4; + + if (iLoadTest() == 1) { + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, psxRegs.code); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + + PUSH32M((u32)&target); + PUSH32I(_Rt_); + CALLFunc((u32)psxDelayTest); + ADD32ItoR(ESP, 2*4); + + RET(); + return; + } + switch( psxRegs.code >> 26 ) { + // Lode Runner (jr - beq) + + // bltz - bgez - bltzal - bgezal / beq - bne - blez - bgtz + case 0x01: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + break; + + default: + recBSC[psxRegs.code>>26](); + break; + } + + iFlushRegs(); + MOV32MtoR(EAX, (u32)&target); + MOV32RtoM((u32)&psxRegs.pc, EAX); + CALLFunc((u32)psxBranchTest); + + iRet(); +} + +static void iJump(u32 branchPC) { + branch = 1; + psxRegs.code = PSXMu32(pc); + pc+=4; + + if (iLoadTest() == 1) { + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, psxRegs.code); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + + PUSH32I(branchPC); + PUSH32I(_Rt_); + CALLFunc((u32)psxDelayTest); + ADD32ItoR(ESP, 2*4); + + RET(); + return; + } + + recBSC[psxRegs.code>>26](); + + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.pc, branchPC); + CALLFunc((u32)psxBranchTest); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + + // maybe just happened an interruption, check so + CMP32ItoM((u32)&psxRegs.pc, branchPC); + j8Ptr[0] = JE8(0); + RET(); + + x86SetJ8(j8Ptr[0]); + MOV32MtoR(EAX, PC_REC(branchPC)); + TEST32RtoR(EAX, EAX); + j8Ptr[1] = JNE8(0); + RET(); + + x86SetJ8(j8Ptr[1]); + RET(); + JMP32R(EAX); +} + +static void iBranch(u32 branchPC, int savectx) { + u32 respold=0; + + if (savectx) { + respold = resp; + memcpy(iRegsS, iRegs, sizeof(iRegs)); + } + + branch = 1; + psxRegs.code = PSXMu32(pc); + + // the delay test is only made when the branch is taken + // savectx == 0 will mean that :) + if (savectx == 0 && iLoadTest() == 1) { + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, psxRegs.code); + /* store cycle */ + count = (((pc+4) - pcold) / 4) * BIAS; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + + PUSH32I(branchPC); + PUSH32I(_Rt_); + CALLFunc((u32)psxDelayTest); + ADD32ItoR(ESP, 2*4); + + RET(); + return; + } + + pc+= 4; + recBSC[psxRegs.code>>26](); + + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.pc, branchPC); + CALLFunc((u32)psxBranchTest); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + + // maybe just happened an interruption, check so + CMP32ItoM((u32)&psxRegs.pc, branchPC); + j8Ptr[1] = JE8(0); + RET(); + + x86SetJ8(j8Ptr[1]); + MOV32MtoR(EAX, PC_REC(branchPC)); + TEST32RtoR(EAX, EAX); + j8Ptr[2] = JNE8(0); + RET(); + + x86SetJ8(j8Ptr[2]); + JMP32R(EAX); + + pc-= 4; + if (savectx) { + resp = respold; + memcpy(iRegs, iRegsS, sizeof(iRegs)); + } +} + + +char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +char *txt1 = "EAX = %x\n"; +char *txt2 = "M32 = %x\n"; + +void iLogX86() { + PUSHA32(); + + PUSH32R (EDX); + PUSH32R (ECX); + PUSH32R (EAX); + PUSH32M ((u32)&txt0); + CALLFunc ((u32)SysPrintf); + ADD32ItoR(ESP, 4*4); + + POPA32(); +} + +void iLogEAX() { + PUSH32R (EAX); + PUSH32M ((u32)&txt1); + CALLFunc ((u32)SysPrintf); + ADD32ItoR(ESP, 4*2); +} + +void iLogM32(u32 mem) { + PUSH32M (mem); + PUSH32M ((u32)&txt2); + CALLFunc ((u32)SysPrintf); + ADD32ItoR(ESP, 4*2); +} + +#if 0 +static void iDumpRegs() { + int i, j; + + printf("%x %x\n", psxRegs.pc, psxRegs.cycle); + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) + printf("%x ", psxRegs.GPR.r[j * i]); + printf("\n"); + } +} +#endif + +void iDumpBlock(char *ptr) { + FILE *f; + u32 i; + + SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle); + + for (i = psxRegs.pc; i < pc; i += 4) + SysPrintf("%s\n", disR3000AF(PSXMu32(i), i)); + + fflush(stdout); + f = fopen("dump1", "w"); + fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f); + fclose(f); + system("ndisasmw -u dump1"); + fflush(stdout); +} + +#define REC_FUNC(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \ + CALLFunc((u32)psx##f); \ +/* branch = 2; */\ +} + +#define REC_SYS(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \ + CALLFunc((u32)psx##f); \ + branch = 2; \ + iRet(); \ +} + +#define REC_BRANCH(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \ + CALLFunc((u32)psx##f); \ + branch = 2; \ + iRet(); \ +} + +static void recRecompile(); + +static int recInit() { + int i; + + psxRecLUT = (u32 *)malloc(0x010000 * 4); + + recMem = mmap(0, RECMEM_SIZE + 0x1000, + PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + recRAM = (char *)malloc(0x200000); + recROM = (char *)malloc(0x080000); + if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) { + SysMessage("Error allocating memory"); return -1; + } + + for (i = 0; i < 0x80; i++) psxRecLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16]; + memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * 4); + memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * 4); + + for (i = 0; i < 0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16]; + + return 0; +} + +static void recReset() { + memset(recRAM, 0, 0x200000); + memset(recROM, 0, 0x080000); + + x86Init(); + + x86SetPtr(recMem); + + branch = 0; + memset(iRegs, 0, sizeof(iRegs)); + iRegs[0].state = ST_CONST; + iRegs[0].k = 0; +} + +static void recShutdown() { + if (recMem == NULL) return; + free(psxRecLUT); + munmap(recMem, RECMEM_SIZE + 0x1000); + free(recRAM); + free(recROM); + x86Shutdown(); +} + +static void recError() { + SysReset(); + ClosePlugins(); + SysMessage("Unrecoverable error while running recompiler\n"); + SysRunGui(); +} + +__inline static void execute() { + void (**recFunc)() = NULL; + char *p; + + p = (char *)PC_REC(psxRegs.pc); + if (p != NULL) recFunc = (void (**)()) (u32)p; + else { recError(); return; } + + if (*recFunc == 0) { + recRecompile(); + } + (*recFunc)(); +} + +static void recExecute() { + for (;;) execute(); +} + +static void recExecuteBlock() { + execute(); +} + +static void recClear(u32 Addr, u32 Size) { + u32 bank,offset; + + bank = Addr >> 24; + offset = Addr & 0xffffff; + + + // Pitfall 3D - clear dynarec slots that contain 'stale' ram data + // - fixes stage 1 loading crash + if( bank == 0x80 || bank == 0xa0 || bank == 0x00 ) { + offset &= 0x1fffff; + + if( offset >= DYNAREC_BLOCK * 4 ) + memset((void*)PC_REC(Addr - DYNAREC_BLOCK * 4), 0, DYNAREC_BLOCK * 4); + else + memset((void*)PC_REC(Addr - offset), 0, offset); + } + + + memset((void*)PC_REC(Addr), 0, Size * 4); +} + +static void recNULL() { +// SysMessage("recUNK: %8.8x\n", psxRegs.code); +} + +/********************************************************* +* goes to opcodes tables... * +* Format: table[something....] * +*********************************************************/ + +//REC_SYS(SPECIAL); +static void recSPECIAL() { + recSPC[_Funct_](); +} + +static void recREGIMM() { + recREG[_Rt_](); +} + +static void recCOP0() { + recCP0[_Rs_](); +} + +//REC_SYS(COP2); +static void recCOP2() { + MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status); + AND32ItoR(EAX, 0x40000000); + j8Ptr[31] = JZ8(0); + + recCP2[_Funct_](); + + x86SetJ8(j8Ptr[31]); +} + +static void recBASIC() { + recCP2BSC[_Rs_](); +} + +//end of Tables opcodes... + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +/*REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); +REC_FUNC(SLTI); +REC_FUNC(SLTIU); +#if 0*/ +static void recADDIU() { +// Rt = Rs + Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k+= _Imm_; + } else { + if (_Imm_ == 1) { + INC32M((u32)&psxRegs.GPR.r[_Rt_]); + } else if (_Imm_ == -1) { + DEC32M((u32)&psxRegs.GPR.r[_Rt_]); + } else if (_Imm_) { + ADD32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_); + } + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k + _Imm_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_ == 1) { + INC32R(EAX); + } else if (_Imm_ == -1) { + DEC32R(EAX); + } else if (_Imm_) { + ADD32ItoR(EAX, _Imm_); + } + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} + +static void recADDI() { +// Rt = Rs + Im + recADDIU(); +} + +static void recSLTI() { +// Rt = Rs < Im (signed) + if (!_Rt_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, _Imm_); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +} + +static void recSLTIU() { +// Rt = Rs < Im (unsigned) + if (!_Rt_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, _Imm_); + SETB8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +} + +static void recANDI() { +// Rt = Rs And Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k&= _ImmU_; + } else { + AND32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_); + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + AND32ItoR(EAX, _ImmU_); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} + +static void recORI() { +// Rt = Rs Or Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k|= _ImmU_; + } else { + OR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_); + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_ImmU_) OR32ItoR (EAX, _ImmU_); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} + +static void recXORI() { +// Rt = Rs Xor Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k^= _ImmU_; + } else { + XOR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_); + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + XOR32ItoR(EAX, _ImmU_); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} +//#endif +//end of * Arithmetic with immediate operand + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +/*REC_FUNC(LUI); +#if 0*/ +static void recLUI() { +// Rt = Imm << 16 + if (!_Rt_) return; + + MapConst(_Rt_, psxRegs.code << 16); +} +//#endif +//End of Load Higher ..... + + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +/*REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#if 0*/ +static void recADDU() { +// Rd = Rs + Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rt_ == _Rd_) { + if (iRegs[_Rs_].k == 1) { + INC32M((u32)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rs_].k == -1) { + DEC32M((u32)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rs_].k) { + ADD32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k); + } + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + if (iRegs[_Rs_].k == 1) { + INC32R(EAX); + } else if (iRegs[_Rs_].k == 0xffffffff) { + DEC32R(EAX); + } else if (iRegs[_Rs_].k) { + ADD32ItoR(EAX, iRegs[_Rs_].k); + } + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rs_ == _Rd_) { + if (iRegs[_Rt_].k == 1) { + INC32M((u32)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rt_].k == -1) { + DEC32M((u32)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rt_].k) { + ADD32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k); + } + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (iRegs[_Rt_].k == 1) { + INC32R(EAX); + } else if (iRegs[_Rt_].k == 0xffffffff) { + DEC32R(EAX); + } else if (iRegs[_Rt_].k) { + ADD32ItoR(EAX, iRegs[_Rt_].k); + } + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } + } else { + iRegs[_Rd_].state = ST_UNK; + + if (_Rs_ == _Rd_) { // Rd+= Rt + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + ADD32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (_Rt_ == _Rd_) { // Rd+= Rs + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + ADD32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { // Rd = Rs + Rt + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + ADD32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } + } +} + +static void recADD() { +// Rd = Rs + Rt + recADDU(); +} + +static void recSUBU() { +// Rd = Rs - Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + SUB32ItoR(EAX, iRegs[_Rt_].k); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSUB() { +// Rd = Rs - Rt + recSUBU(); +} + +static void recAND() { +// Rd = Rs And Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rd_ == _Rt_) { // Rd&= Rs + AND32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k); + } else { + MOV32ItoR(EAX, iRegs[_Rs_].k); + AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rd_ == _Rs_) { // Rd&= kRt + AND32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k); + } else { // Rd = Rs & kRt + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + AND32ItoR(EAX, iRegs[_Rt_].k); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } + } else { + iRegs[_Rd_].state = ST_UNK; + + if (_Rs_ == _Rd_) { // Rd&= Rt + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + AND32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (_Rt_ == _Rd_) { // Rd&= Rs + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + AND32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { // Rd = Rs & Rt + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } + } +} + +static void recOR() { +// Rd = Rs Or Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + OR32ItoR (EAX, iRegs[_Rt_].k); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recXOR() { +// Rd = Rs Xor Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + XOR32ItoR(EAX, iRegs[_Rt_].k); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recNOR() { +// Rd = Rs Nor Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k)); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]); + NOT32R (EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + OR32ItoR (EAX, iRegs[_Rt_].k); + NOT32R (EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]); + NOT32R (EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSLT() { +// Rd = Rs < Rt (signed) + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, iRegs[_Rt_].k); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSLTU() { +// Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, iRegs[_Rt_].k); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} +//#endif +//End of * Register arithmetic + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +/*REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC(DIV); +REC_FUNC(DIVU); +#if 0*/ +static void recMULT() { +// Lo/Hi = Rs * Rt (signed) + +// iFlushRegs(); + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || + (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { + XOR32RtoR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + return; + } + + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + } + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k); + IMUL32R (EDX); + } else { + IMUL32M ((u32)&psxRegs.GPR.r[_Rt_]); + } + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX); +} + +static void recMULTU() { +// Lo/Hi = Rs * Rt (unsigned) + +// iFlushRegs(); + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || + (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { + XOR32RtoR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + return; + } + + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + } + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k); + MUL32R (EDX); + } else { + MUL32M ((u32)&psxRegs.GPR.r[_Rt_]); + } + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX); +} + +static void recDIV() { +// Lo/Hi = Rs / Rt (signed) + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + if (iRegs[_Rt_].k == 0) { + MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + } + return; + } + MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + } + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + } + CDQ(); + IDIV32R (ECX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX); + + if (!IsConst(_Rt_)) { + j8Ptr[1] = JMP8(1); + + x86SetJ8(j8Ptr[0]); + + MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + } + + x86SetJ8(j8Ptr[1]); + } +} + +static void recDIVU() { +// Lo/Hi = Rs / Rt (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + if (iRegs[_Rt_].k == 0) { + MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + } + return; + } + MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + } + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + } + XOR32RtoR(EDX, EDX); + DIV32R (ECX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX); + + if (!IsConst(_Rt_)) { + j8Ptr[1] = JMP8(1); + + x86SetJ8(j8Ptr[0]); + + MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + } + + x86SetJ8(j8Ptr[1]); + } +} +//#endif +//End of * Register mult/div & Register trap logic + +/*REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); + +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW);*/ + +//REC_FUNC(LWL); +//REC_FUNC(LWR); +//REC_FUNC(SWL); +//REC_FUNC(SWR); + +/* Push OfB for Stores/Loads */ +static void iPushOfB() { + if (IsConst(_Rs_)) { + PUSH32I (iRegs[_Rs_].k + _Imm_); + } else { + if (_Imm_) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + } else { + PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]); + } + } +} + +//#if 0 +static void recLB() { +// Rt = mem[Rs + Im] (signed) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRs8(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M8toR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } +// SysPrintf("unhandled r8 %x\n", addr); + } + + iPushOfB(); + CALLFunc((u32)psxMemRead8); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVSX32R8toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +static void recLBU() { +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu8(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M8toR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } +// SysPrintf("unhandled r8u %x\n", addr); + } + + iPushOfB(); + CALLFunc((u32)psxMemRead8); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVZX32R8toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +static void recLH() { +// Rt = mem[Rs + Im] (signed) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRs16(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M16toR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } +// SysPrintf("unhandled r16 %x\n", addr); + } + + iPushOfB(); + CALLFunc((u32)psxMemRead16); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVSX32R16toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +static void recLHU() { +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu16(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M16toR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80) { + if (addr >= 0x1f801c00 && addr < 0x1f801e00) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + PUSH32I (addr); + CALL32M ((u32)&SPU_readRegister); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); +#ifndef __WIN32__ + resp+= 4; +#endif + return; + } + switch (addr) { + case 0x1f801100: case 0x1f801110: case 0x1f801120: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + PUSH32I((addr >> 4) & 0x3); + CALLFunc((u32)psxRcntRcount); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + resp+= 4; + return; + + case 0x1f801104: case 0x1f801114: case 0x1f801124: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + PUSH32I((addr >> 4) & 0x3); + CALLFunc((u32)psxRcntRmode); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + resp+= 4; + return; + + case 0x1f801108: case 0x1f801118: case 0x1f801128: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + PUSH32I((addr >> 4) & 0x3); + CALLFunc((u32)psxRcntRtarget); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + resp+= 4; + return; + } + } +// SysPrintf("unhandled r16u %x\n", addr); + } + + iPushOfB(); + CALLFunc((u32)psxMemRead16); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +static void recLW() { +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu32(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80) { + switch (addr) { + case 0x1f801080: case 0x1f801084: case 0x1f801088: + case 0x1f801090: case 0x1f801094: case 0x1f801098: + case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8: + case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8: + case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8: + case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8: + case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8: + case 0x1f801070: case 0x1f801074: + case 0x1f8010f0: case 0x1f8010f4: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + + case 0x1f801810: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + CALL32M((u32)&GPU_readData); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + + case 0x1f801814: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + CALL32M((u32)&GPU_readStatus); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } +// SysPrintf("unhandled r32 %x\n", addr); + } + + iPushOfB(); + CALLFunc((u32)psxMemRead32); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +extern u32 LWL_MASK[4]; +extern u32 LWL_SHIFT[4]; + +void iLWLk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32ItoR(ECX, LWL_MASK[shift]); + SHL32ItoR(EAX, LWL_SHIFT[shift]); + OR32RtoR (EAX, ECX); +} + +void recLWL() { +// Rt = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iLWLk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iLWLk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + CALLFunc((u32)psxMemRead32); + + if (_Rt_) { + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)LWL_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift] + + MOV32ItoR(ECX, (u32)LWL_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift] + + OR32RtoR(EAX, EDX); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } else { +// ADD32ItoR(ESP, 8); + resp+= 8; + } +} + +#if 0 +static void recLWBlock(int count) { + u32 *code = (u32 *)PSXM(pc); + int i, respsave; +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + // since bios is readonly it won't change + for (i = 0; i < count; i++, code++, addr += 4) { + if (_fRt_(*code)) { + MapConst(_fRt_(*code), psxRu32(addr)); + } + } + return; + } + if ((t & 0x1fe0) == 0) { + for (i = 0; i < count; i++, code++, addr += 4) { + if (!_fRt_(*code)) + return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + for (i = 0; i < count; i++, code++, addr += 4) { + if (!_fRt_(*code)) + return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + } + + SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_)); + iPushOfB(); + CALLFunc((u32)psxMemPointer); +// ADD32ItoR(ESP, 4); + resp += 4; + + respsave = resp; resp = 0; + TEST32RtoR(EAX, EAX); + j32Ptr[4] = JZ32(0); + XOR32RtoR(ECX, ECX); + for (i = 0; i < count; i++, code++) { + if (_fRt_(*code)) { + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32RmStoR(EDX, EAX, ECX, 2); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX); + } + if (i != (count - 1)) + INC32R(ECX); + } + j32Ptr[5] = JMP32(0); + x86SetJ32(j32Ptr[4]); + for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) { + psxRegs.code = *code; + recLW(); + } + ADD32ItoR(ESP, resp); + x86SetJ32(j32Ptr[5]); + resp = respsave; +} +#endif + +extern u32 LWR_MASK[4]; +extern u32 LWR_SHIFT[4]; + +void iLWRk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32ItoR(ECX, LWR_MASK[shift]); + SHR32ItoR(EAX, LWR_SHIFT[shift]); + OR32RtoR(EAX, ECX); +} + +void recLWR() { +// Rt = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iLWRk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iLWRk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } + + if (IsConst(_Rs_)) + MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + CALLFunc((u32)psxMemRead32); + + if (_Rt_) { + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)LWR_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift] + + MOV32ItoR(ECX, (u32)LWR_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift] + + OR32RtoR(EAX, EDX); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } else { +// ADD32ItoR(ESP, 8); + resp+= 8; + } +} + +static void recSB() { +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k); + } else { + MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + + PUSH32I(1); + PUSH32I(addr & ~3); + CALLFunc((u32)&recClear); + resp += 8; + return; + } + + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k); + } else { + MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV8RtoM((u32)&psxH[addr & 0xfff], EAX); + } + return; + } +// SysPrintf("unhandled w8 %x\n", addr); + } + + if (IsConst(_Rt_)) { + PUSH32I (iRegs[_Rt_].k); + } else { + PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]); + } + iPushOfB(); + CALLFunc((u32)psxMemWrite8); +// ADD32ItoR(ESP, 8); + resp+= 8; +} + +static void recSH() { +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k); + } else { + MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + + PUSH32I(1); + PUSH32I(addr & ~3); + CALLFunc((u32)&recClear); + resp += 8; + return; + } + + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k); + } else { + MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV16RtoM((u32)&psxH[addr & 0xfff], EAX); + } + return; + } + if (t == 0x1f80) { + if (addr >= 0x1f801c00 && addr < 0x1f801e00) { + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + PUSH32I (addr); + CALL32M ((u32)&SPU_writeRegister); +#ifndef __WIN32__ + resp+= 8; +#endif + return; + } + } +// SysPrintf("unhandled w16 %x\n", addr); + } + + if (IsConst(_Rt_)) { + PUSH32I (iRegs[_Rt_].k); + } else { + PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]); + } + iPushOfB(); + CALLFunc((u32)psxMemWrite16); +// ADD32ItoR(ESP, 8); + resp+= 8; +} + +static void recSW() { +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + + PUSH32I(1); + PUSH32I(addr); + CALLFunc((u32)&recClear); + resp += 8; + return; + } + + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV32ItoM((u32)&psxH[addr & 0xfff], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxH[addr & 0xfff], EAX); + } + return; + } + if (t == 0x1f80) { + switch (addr) { + case 0x1f801080: case 0x1f801084: + case 0x1f801090: case 0x1f801094: + case 0x1f8010a0: case 0x1f8010a4: + case 0x1f8010b0: case 0x1f8010b4: + case 0x1f8010c0: case 0x1f8010c4: + case 0x1f8010d0: case 0x1f8010d4: + case 0x1f8010e0: case 0x1f8010e4: + case 0x1f801074: + case 0x1f8010f0: + if (IsConst(_Rt_)) { + MOV32ItoM((u32)&psxH[addr & 0xffff], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxH[addr & 0xffff], EAX); + } + return; + + case 0x1f801810: + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + CALL32M((u32)&GPU_writeData); +#ifndef __WIN32__ + resp+= 4; +#endif + return; + + case 0x1f801814: + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + CALL32M((u32)&GPU_writeStatus); +#ifndef __WIN32__ + resp+= 4; +#endif + return; + } + } +// SysPrintf("unhandled w32 %x\n", addr); + } + + if (IsConst(_Rt_)) { + PUSH32I (iRegs[_Rt_].k); + } else { + PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]); + } + iPushOfB(); + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp+= 8; +} +//#endif + +#if 0 +static void recSWBlock(int count) { + u32 *code; + int i, respsave; +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + code = (u32 *)PSXM(pc); + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + for (i = 0; i < count; i++, code++, addr += 4) { + if (IsConst(_fRt_(*code))) { + MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]); + MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + for (i = 0; i < count; i++, code++, addr += 4) { + if (!_fRt_(*code)) + return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + } + + SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_)); + iPushOfB(); + CALLFunc((u32)psxMemPointer); +// ADD32ItoR(ESP, 4); + resp += 4; + + respsave = resp; + resp = 0; + TEST32RtoR(EAX, EAX); + j32Ptr[4] = JZ32(0); + XOR32RtoR(ECX, ECX); + for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) { + if (IsConst(_fRt_(*code))) { + MOV32ItoR(EDX, iRegs[_fRt_(*code)].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]); + } + MOV32RtoRmS(EAX, ECX, 2, EDX); + if (i != (count - 1)) + INC32R(ECX); + } + j32Ptr[5] = JMP32(0); + x86SetJ32(j32Ptr[4]); + for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) { + psxRegs.code = *code; + recSW(); + } + ADD32ItoR(ESP, resp); + x86SetJ32(j32Ptr[5]); + resp = respsave; +} +#endif + +extern u32 SWL_MASK[4]; +extern u32 SWL_SHIFT[4]; + +void iSWLk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHR32ItoR(ECX, SWL_SHIFT[shift]); + AND32ItoR(EAX, SWL_MASK[shift]); + OR32RtoR (EAX, ECX); +} + +void recSWL() { +// mem[Rs + Im] = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + +#if 0 + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iSWLk(addr & 3); + MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX); + return; + } +#endif + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iSWLk(addr & 3); + MOV32RtoM((u32)&psxH[addr & 0xffc], EAX); + return; + } + } + + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemRead32); + + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)SWL_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift] + + MOV32ItoR(ECX, (u32)SWL_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift] + + OR32RtoR (EAX, EDX); + PUSH32R (EAX); + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp+= 8; +} + +extern u32 SWR_MASK[4]; +extern u32 SWR_SHIFT[4]; + +void iSWRk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHL32ItoR(ECX, SWR_SHIFT[shift]); + AND32ItoR(EAX, SWR_MASK[shift]); + OR32RtoR (EAX, ECX); +} + +void recSWR() { +// mem[Rs + Im] = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + +#if 0 + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iSWRk(addr & 3); + MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX); + return; + } +#endif + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iSWRk(addr & 3); + MOV32RtoM((u32)&psxH[addr & 0xffc], EAX); + return; + } + } + + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemRead32); + + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)SWR_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift] + + MOV32ItoR(ECX, (u32)SWR_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift] + + OR32RtoR (EAX, EDX); + PUSH32R (EAX); + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp += 8; +} + +/*REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +#if 0*/ +static void recSLL() { +// Rd = Rt << Sa + if (!_Rd_) + return; + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rt_].k << _Sa_); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + if (_Sa_) SHL32ItoR(EAX, _Sa_); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRL() { +// Rd = Rt >> Sa + if (!_Rd_) + return; + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + if (_Sa_) SHR32ItoR(EAX, _Sa_); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRA() { +// Rd = Rt >> Sa + if (!_Rd_) + return; + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + if (_Sa_) SAR32ItoR(EAX, _Sa_); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} +//#endif + +/*REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +#if 0*/ +static void recSLLV() { +// Rd = Rt << Rs + if (!_Rd_) + return; + +// iFlushRegs(); + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32ItoR(ECX, iRegs[_Rs_].k); + SHL32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rt_].k); + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRLV() { +// Rd = Rt >> Rs + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32ItoR(ECX, iRegs[_Rs_].k); + SHR32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rt_].k); + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRAV() { +// Rd = Rt >> Rs + if (!_Rd_) + return; + +// iFlushRegs(); + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32ItoR(ECX, iRegs[_Rs_].k); + SAR32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rt_].k); + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + } +} +//#endif + +/*REC_SYS(SYSCALL); +REC_SYS(BREAK); + +#if 0*/ +int dump; +static void recSYSCALL() { +// dump = 1; + iFlushRegs(); + + MOV32ItoR(EAX, pc - 4); + MOV32RtoM((u32)&psxRegs.pc, EAX); + PUSH32I (branch == 1 ? 1 : 0); + PUSH32I (0x20); + CALLFunc ((u32)psxException); + ADD32ItoR(ESP, 8); + + branch = 2; + iRet(); +} + +static void recBREAK() { +} +//#endif + +/*REC_FUNC(MFHI); +REC_FUNC(MTHI); +REC_FUNC(MFLO); +REC_FUNC(MTLO); +#if 0*/ +static void recMFHI() { +// Rd = Hi + if (!_Rd_) + return; + + iRegs[_Rd_].state = ST_UNK; + MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.hi); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); +} + +static void recMTHI() { +// Hi = Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + } +} + +static void recMFLO() { +// Rd = Lo + if (!_Rd_) + return; + + iRegs[_Rd_].state = ST_UNK; + MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.lo); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); +} + +static void recMTLO() { +// Lo = Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&psxRegs.GPR.n.lo, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + } +} +//#endif + +/*REC_BRANCH(J); +REC_BRANCH(JR); +REC_BRANCH(JAL); +REC_BRANCH(JALR); +REC_BRANCH(BLTZ); +REC_BRANCH(BGTZ); +REC_BRANCH(BLTZAL); +REC_BRANCH(BGEZAL); +REC_BRANCH(BNE); +REC_BRANCH(BEQ); +REC_BRANCH(BLEZ); +REC_BRANCH(BGEZ);*/ + +//#if 0 +static void recBLTZ() { +// Branch if Rs < 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k < 0) { + iJump(bpc); + return; + } else { + iJump(pc + 4); + return; + } + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JL32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc += 4; +} + +static void recBGTZ() { +// Branch if Rs > 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k > 0) { + iJump(bpc); + return; + } else { + iJump(pc + 4); + return; + } + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JG32(0); + + iBranch(pc + 4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBLTZAL() { +// Branch if Rs < 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k < 0) { + MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4); + iJump(bpc); return; + } else { + iJump(pc + 4); return; + } + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JL32(0); + + iBranch(pc + 4, 1); + + x86SetJ32(j32Ptr[4]); + + MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4); + iBranch(bpc, 0); + pc += 4; +} + +static void recBGEZAL() { +// Branch if Rs >= 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k >= 0) { + MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4); + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JGE32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4); + iBranch(bpc, 0); + pc+=4; +} + +static void recJ() { +// j target + + iJump(_Target_ * 4 + (pc & 0xf0000000)); +} + +static void recJAL() { +// jal target + + MapConst(31, pc + 4); + + iJump(_Target_ * 4 + (pc & 0xf0000000)); +} + +static void recJR() { +// jr Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&target, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&target, EAX); + } + + SetBranch(); +} + +static void recJALR() { +// jalr Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((u32)&target, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((u32)&target, EAX); + } + + if (_Rd_) { + MapConst(_Rd_, pc + 4); + } + + SetBranch(); +} + +static void recBEQ() { +// Branch if Rs == Rt + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (_Rs_ == _Rt_) { + iJump(bpc); + } else { + if (IsConst(_Rs_) && IsConst(_Rt_)) { + if (iRegs[_Rs_].k == iRegs[_Rt_].k) { + iJump(bpc); + return; + } else { + iJump(pc + 4); + return; + } + } else if (IsConst(_Rs_)) { + CMP32ItoM((u32)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k); + } else if (IsConst(_Rt_)) { + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + } + + j32Ptr[4] = JE32(0); + + iBranch(pc + 4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc += 4; + } +} + +static void recBNE() { +// Branch if Rs != Rt + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + if (iRegs[_Rs_].k != iRegs[_Rt_].k) { + iJump(bpc); + return; + } else { + iJump(pc + 4); + return; + } + } else if (IsConst(_Rs_)) { + CMP32ItoM((u32)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k); + } else if (IsConst(_Rt_)) { + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + } + j32Ptr[4] = JNE32(0); + + iBranch(pc + 4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc += 4; +} + +static void recBLEZ() { +// Branch if Rs <= 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k <= 0) { + iJump(bpc); + return; + } else { + iJump(pc + 4); + return; + } + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JLE32(0); + + iBranch(pc + 4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc += 4; +} + +static void recBGEZ() { +// Branch if Rs >= 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k >= 0) { + iJump(bpc); + return; + } else { + iJump(pc + 4); + return; + } + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JGE32(0); + + iBranch(pc + 4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc += 4; +} +//#endif + +/*REC_FUNC(MFC0); +REC_SYS(MTC0); +REC_FUNC(CFC0); +REC_SYS(CTC0); +REC_FUNC(RFE); +#if 0*/ +static void recMFC0() { +// Rt = Cop0->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + MOV32MtoR(EAX, (u32)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); +} + +static void recCFC0() { +// Rt = Cop0->Rd + + recMFC0(); +} + +void psxMTC0(); +static void recMTC0() { +// Cop0->Rd = Rt + + if (IsConst(_Rt_)) { + switch (_Rd_) { + case 12: + MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); + break; + case 13: + MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00)); + break; + default: + MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); + break; + } + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + switch (_Rd_) { + case 13: + AND32ItoR(EAX, ~(0xfc00)); + break; + } + MOV32RtoM((u32)&psxRegs.CP0.r[_Rd_], EAX); + } + + if (_Rd_ == 12 || _Rd_ == 13) { + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.pc, (u32)pc); + CALLFunc((u32)psxTestSWInts); + if (branch == 0) { + branch = 2; + iRet(); + } + } +} + +static void recCTC0() { +// Cop0->Rd = Rt + + recMTC0(); +} + +static void recRFE() { + MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status); + MOV32RtoR(ECX, EAX); + AND32ItoR(EAX, 0xfffffff0); + AND32ItoR(ECX, 0x3c); + SHR32ItoR(ECX, 2); + OR32RtoR (EAX, ECX); + MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX); + + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.pc, (u32)pc); + CALLFunc((u32)psxTestSWInts); + if (branch == 0) { + branch = 2; + iRet(); + } +} +//#endif + +#include "iGte.h" + +// + +static void recHLE() { + iFlushRegs(); + + MOV32ItoR(EAX, (u32)psxHLEt[psxRegs.code & 0xffff]); + CALL32R(EAX); + branch = 2; + iRet(); +} + +// + +static void (*recBSC[64])() = { + recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ, + recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI , + recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL, + recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL, + recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL, + recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL +}; + +static void (*recSPC[64])() = { + recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV, + recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL, + recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL, + recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL, + recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR , + recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL +}; + +static void (*recREG[32])() = { + recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL +}; + +static void (*recCP0[32])() = { + recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL +}; + +static void (*recCP2[64])() = { + recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00 + recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08 + recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10 + recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18 + recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20 + recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28 + recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30 + recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38 +}; + +static void (*recCP2BSC[32])() = { + recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, 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 +}; + +static void recRecompile() { + char *p; + char *ptr; + + dump = 0; + resp = 0; + + /* if x86Ptr reached the mem limit reset whole mem */ + if (((u32)x86Ptr - (u32)recMem) >= (RECMEM_SIZE - 0x10000)) + recReset(); + + x86Align(32); + ptr = x86Ptr; + + PC_REC32(psxRegs.pc) = (u32)x86Ptr; + pc = psxRegs.pc; + pcold = pc; + + for (count = 0; count < DYNAREC_BLOCK;) { + p = (char *)PSXM(pc); + if (p == NULL) recError(); + psxRegs.code = *(u32 *)p; +/* + if ((psxRegs.code >> 26) == 0x23) { // LW + int i; + u32 code; + + for (i=1;; i++) { + p = (char *)PSXM(pc+i*4); + if (p == NULL) recError(); + code = *(u32 *)p; + + if ((code >> 26) != 0x23 || + _fRs_(code) != _Rs_ || + _fImm_(code) != (_Imm_+i*4)) + break; + } + if (i > 1) { + recLWBlock(i); + pc = pc + i*4; continue; + } + } + + if ((psxRegs.code >> 26) == 0x2b) { // SW + int i; + u32 code; + + for (i=1;; i++) { + p = (char *)PSXM(pc+i*4); + if (p == NULL) recError(); + code = *(u32 *)p; + + if ((code >> 26) != 0x2b || + _fRs_(code) != _Rs_ || + _fImm_(code) != (_Imm_+i*4)) + break; + } + if (i > 1) { + recSWBlock(i); + pc = pc + i*4; continue; + } + }*/ + + pc += 4; + count++; + recBSC[psxRegs.code >> 26](); + + if (branch) { + branch = 0; + if (dump) iDumpBlock(ptr); + return; + } + } + + iFlushRegs(); + + MOV32ItoM((u32)&psxRegs.pc, pc); + + iRet(); +} + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; + +#endif diff --git a/libpcsxcore/ix86/ix86.c b/libpcsxcore/ix86/ix86.c index ef615820..06275ffa 100644..100755 --- a/libpcsxcore/ix86/ix86.c +++ b/libpcsxcore/ix86/ix86.c @@ -1,1727 +1,1727 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
- * ix86 core v0.5.1
- * Authors: linuzappz <linuzappz@pcsx.net>
- * alexey silinov
- */
-
-#ifdef __i386__
-
-#include "ix86.h"
-
-s8 *x86Ptr;
-u8 *j8Ptr[32];
-u32 *j32Ptr[32];
-
-void x86Init() {
-}
-
-void x86SetPtr(char *ptr) {
- x86Ptr = ptr;
-}
-
-void x86Shutdown() {
-}
-
-void x86SetJ8(u8 *j8) {
- u32 jump = (x86Ptr - (s8*)j8) - 1;
-
- if (jump > 0x7f) printf("j8 greater than 0x7f!!\n");
- *j8 = (u8)jump;
-}
-
-void x86SetJ32(u32 *j32) {
- *j32 = (x86Ptr - (s8*)j32) - 4;
-}
-
-void x86Align(int bytes) {
- // fordward align
- x86Ptr = (s8*)(((u32)x86Ptr + bytes) & ~(bytes - 1));
-}
-
-#define SIB 4
-#define DISP32 5
-
-/* macros helpers */
-
-#define ModRM(mod, rm, reg) \
- write8((mod << 6) | (rm << 3) | (reg));
-
-#define SibSB(ss, rm, index) \
- write8((ss << 6) | (rm << 3) | (index));
-
-#define SET8R(cc, to) { \
- write8(0x0F); write8(cc); \
- write8((0xC0) | (to)); }
-
-#define J8Rel(cc, to) { \
- write8(cc); write8(to); return x86Ptr - 1; }
-
-#define J32Rel(cc, to) { \
- write8(0x0F); write8(cc); write32(to); return (u32*)(x86Ptr - 4); }
-
-#define CMOV32RtoR(cc, to, from) { \
- write8(0x0F); write8(cc); \
- ModRM(3, to, from); }
-
-#define CMOV32MtoR(cc, to, from) { \
- write8(0x0F); write8(cc); \
- ModRM(0, to, DISP32); \
- write32(from); }
-
-/********************/
-/* IX86 intructions */
-/********************/
-
-// mov instructions
-
-/* mov r32 to r32 */
-void MOV32RtoR(int to, int from) {
- write8(0x89);
- ModRM(3, from, to);
-}
-
-/* mov r32 to m32 */
-void MOV32RtoM(u32 to, int from) {
- write8(0x89);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* mov m32 to r32 */
-void MOV32MtoR(int to, u32 from) {
- write8(0x8B);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* mov [r32] to r32 */
-void MOV32RmtoR(int to, int from) {
- write8(0x8B);
- ModRM(0, to, from);
-}
-
-/* mov [r32][r32*scale] to r32 */
-void MOV32RmStoR(int to, int from, int from2, int scale) {
- write8(0x8B);
- ModRM(0, to, 0x4);
- SibSB(scale, from2, from);
-}
-
-/* mov r32 to [r32] */
-void MOV32RtoRm(int to, int from) {
- write8(0x89);
- ModRM(0, from, to);
-}
-
-/* mov r32 to [r32][r32*scale] */
-void MOV32RtoRmS(int to, int to2, int scale, int from) {
- write8(0x89);
- ModRM(0, from, 0x4);
- SibSB(scale, to2, to);
-}
-
-/* mov imm32 to r32 */
-void MOV32ItoR(int to, u32 from) {
- write8(0xB8 | to);
- write32(from);
-}
-
-/* mov imm32 to m32 */
-void MOV32ItoM(u32 to, u32 from) {
- write8(0xC7);
- ModRM(0, 0, DISP32);
- write32(to);
- write32(from);
-}
-
-/* mov r16 to m16 */
-void MOV16RtoM(u32 to, int from) {
- write8(0x66);
- write8(0x89);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* mov m16 to r16 */
-void MOV16MtoR(int to, u32 from) {
- write8(0x66);
- write8(0x8B);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* mov imm16 to m16 */
-void MOV16ItoM(u32 to, u16 from) {
- write8(0x66);
- write8(0xC7);
- ModRM(0, 0, DISP32);
- write32(to);
- write16(from);
-}
-
-/* mov r8 to m8 */
-void MOV8RtoM(u32 to, int from) {
- write8(0x88);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* mov m8 to r8 */
-void MOV8MtoR(int to, u32 from) {
- write8(0x8A);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* mov imm8 to m8 */
-void MOV8ItoM(u32 to, u8 from) {
- write8(0xC6);
- ModRM(0, 0, DISP32);
- write32(to);
- write8(from);
-}
-
-/* movsx r8 to r32 */
-void MOVSX32R8toR(int to, int from) {
- write16(0xBE0F);
- ModRM(3, to, from);
-}
-
-/* movsx m8 to r32 */
-void MOVSX32M8toR(int to, u32 from) {
- write16(0xBE0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* movsx r16 to r32 */
-void MOVSX32R16toR(int to, int from) {
- write16(0xBF0F);
- ModRM(3, to, from);
-}
-
-/* movsx m16 to r32 */
-void MOVSX32M16toR(int to, u32 from) {
- write16(0xBF0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* movzx r8 to r32 */
-void MOVZX32R8toR(int to, int from) {
- write16(0xB60F);
- ModRM(3, to, from);
-}
-
-/* movzx m8 to r32 */
-void MOVZX32M8toR(int to, u32 from) {
- write16(0xB60F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* movzx r16 to r32 */
-void MOVZX32R16toR(int to, int from) {
- write16(0xB70F);
- ModRM(3, to, from);
-}
-
-/* movzx m16 to r32 */
-void MOVZX32M16toR(int to, u32 from) {
- write16(0xB70F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* cmovne r32 to r32 */
-void CMOVNE32RtoR(int to, int from) {
- CMOV32RtoR(0x45, to, from);
-}
-
-/* cmovne m32 to r32*/
-void CMOVNE32MtoR(int to, u32 from) {
- CMOV32MtoR(0x45, to, from);
-}
-
-/* cmove r32 to r32*/
-void CMOVE32RtoR(int to, int from) {
- CMOV32RtoR(0x44, to, from);
-}
-
-/* cmove m32 to r32*/
-void CMOVE32MtoR(int to, u32 from) {
- CMOV32MtoR(0x44, to, from);
-}
-
-/* cmovg r32 to r32*/
-void CMOVG32RtoR(int to, int from) {
- CMOV32RtoR(0x4F, to, from);
-}
-
-/* cmovg m32 to r32*/
-void CMOVG32MtoR(int to, u32 from) {
- CMOV32MtoR(0x4F, to, from);
-}
-
-/* cmovge r32 to r32*/
-void CMOVGE32RtoR(int to, int from) {
- CMOV32RtoR(0x4D, to, from);
-}
-
-/* cmovge m32 to r32*/
-void CMOVGE32MtoR(int to, u32 from) {
- CMOV32MtoR(0x4D, to, from);
-}
-
-/* cmovl r32 to r32*/
-void CMOVL32RtoR(int to, int from) {
- CMOV32RtoR(0x4C, to, from);
-}
-
-/* cmovl m32 to r32*/
-void CMOVL32MtoR(int to, u32 from) {
- CMOV32MtoR(0x4C, to, from);
-}
-
-/* cmovle r32 to r32*/
-void CMOVLE32RtoR(int to, int from) {
- CMOV32RtoR(0x4E, to, from);
-}
-
-/* cmovle m32 to r32*/
-void CMOVLE32MtoR(int to, u32 from) {
- CMOV32MtoR(0x4E, to, from);
-}
-
-// arithmic instructions
-
-/* add imm32 to r32 */
-void ADD32ItoR(int to, u32 from) {
- 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(to);
- write32(from);
-}
-
-/* add r32 to r32 */
-void ADD32RtoR(int to, int from) {
- write8(0x01);
- ModRM(3, from, to);
-}
-
-/* add r32 to m32 */
-void ADD32RtoM(u32 to, int from) {
- write8(0x01);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* add m32 to r32 */
-void ADD32MtoR(int to, u32 from) {
- write8(0x03);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* adc imm32 to r32 */
-void ADC32ItoR(int to, u32 from) {
- if (to == EAX) {
- write8(0x15);
- } else {
- write8(0x81);
- ModRM(3, 2, to);
- }
- write32(from);
-}
-
-/* adc r32 to r32 */
-void ADC32RtoR(int to, int from) {
- write8(0x11);
- ModRM(3, from, to);
-}
-
-/* adc m32 to r32 */
-void ADC32MtoR(int to, u32 from) {
- write8(0x13);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* inc r32 */
-void INC32R(int to) {
- write8(0x40 + to);
-}
-
-/* inc m32 */
-void INC32M(u32 to) {
- write8(0xFF);
- ModRM(0, 0, DISP32);
- write32(to);
-}
-
-/* sub imm32 to r32 */
-void SUB32ItoR(int to, u32 from) {
- if (to == EAX) {
- write8(0x2D);
- } else {
- write8(0x81);
- ModRM(3, 5, to);
- }
- write32(from);
-}
-
-/* sub r32 to r32 */
-void SUB32RtoR(int to, int from) {
- write8(0x29);
- ModRM(3, from, to);
-}
-
-/* sub m32 to r32 */
-void SUB32MtoR(int to, u32 from) {
- write8(0x2B);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* sbb imm32 to r32 */
-void SBB32ItoR(int to, u32 from) {
- if (to == EAX) {
- write8(0x1D);
- } else {
- write8(0x81);
- ModRM(3, 3, to);
- }
- write32(from);
-}
-
-/* sbb r32 to r32 */
-void SBB32RtoR(int to, int from) {
- write8(0x19);
- ModRM(3, from, to);
-}
-
-/* sbb m32 to r32 */
-void SBB32MtoR(int to, u32 from) {
- write8(0x1B);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* dec r32 */
-void DEC32R(int to) {
- write8(0x48 + to);
-}
-
-/* dec m32 */
-void DEC32M(u32 to) {
- write8(0xFF);
- ModRM(0, 1, DISP32);
- write32(to);
-}
-
-/* mul eax by r32 to edx:eax */
-void MUL32R(int from) {
- write8(0xF7);
- ModRM(3, 4, from);
-}
-
-/* imul eax by r32 to edx:eax */
-void IMUL32R(int 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(from);
-}
-
-/* imul eax by m32 to edx:eax */
-void IMUL32M(u32 from) {
- write8(0xF7);
- ModRM(0, 5, DISP32);
- write32(from);
-}
-
-/* imul r32 by r32 to r32 */
-void IMUL32RtoR(int to, int from) {
- write16(0xAF0F);
- ModRM(3, to, from);
-}
-
-/* div eax by r32 to edx:eax */
-void DIV32R(int from) {
- write8(0xF7);
- ModRM(3, 6, from);
-}
-
-/* idiv eax by r32 to edx:eax */
-void IDIV32R(int 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(from);
-}
-
-/* idiv eax by m32 to edx:eax */
-void IDIV32M(u32 from) {
- write8(0xF7);
- ModRM(0, 7, DISP32);
- write32(from);
-}
-
-// shifting instructions
-
-void RCR32ItoR(int to,int from)
-{
- if (from==1)
- {
- write8(0xd1);
- write8(0xd8 | to);
- }
- else
- {
- write8(0xc1);
- write8(0xd8 | to);
- write8(from);
- }
-}
-
-/* shl imm8 to r32 */
-void SHL32ItoR(int to, u8 from) {
- if (from==1)
- {
- write8(0xd1);
- write8(0xe0 | to);
- return;
- }
- write8(0xC1);
- ModRM(3, 4, to);
- write8(from);
-}
-
-/* shl cl to r32 */
-void SHL32CLtoR(int to) {
- write8(0xD3);
- ModRM(3, 4, to);
-}
-
-/* shr imm8 to r32 */
-void SHR32ItoR(int to, u8 from) {
- if (from==1)
- {
- write8(0xd1);
- write8(0xe8 | to);
- return;
- }
- write8(0xC1);
- ModRM(3, 5, to);
- write8(from);
-}
-
-/* shr cl to r32 */
-void SHR32CLtoR(int to) {
- write8(0xD3);
- ModRM(3, 5, to);
-}
-
-/* sar imm8 to r32 */
-void SAR32ItoR(int to, u8 from) {
- write8(0xC1);
- ModRM(3, 7, to);
- write8(from);
-}
-
-/* sar cl to r32 */
-void SAR32CLtoR(int to) {
- write8(0xD3);
- ModRM(3, 7, to);
-}
-
-
-// logical instructions
-
-/* or imm32 to r32 */
-void OR32ItoR(int 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(to);
- write32(from);
-}
-
-/* or r32 to r32 */
-void OR32RtoR(int to, int from) {
- write8(0x09);
- ModRM(3, from, to);
-}
-
-/* or r32 to m32 */
-void OR32RtoM(u32 to, int from) {
- write8(0x09);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* or m32 to r32 */
-void OR32MtoR(int to, u32 from) {
- write8(0x0B);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* xor imm32 to r32 */
-void XOR32ItoR(int 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(to);
- write32(from);
-}
-
-/* xor r32 to r32 */
-void XOR32RtoR(int to, int from) {
- write8(0x31);
- ModRM(3, from, to);
-}
-
-/* xor r32 to m32 */
-void XOR32RtoM(u32 to, int from) {
- write8(0x31);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* xor m32 to r32 */
-void XOR32MtoR(int to, u32 from) {
- write8(0x33);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* and imm32 to r32 */
-void AND32ItoR(int to, u32 from) {
- if (to == EAX) {
- write8(0x25);
- } else {
- write8(0x81);
- ModRM(3, 0x4, to);
- }
- write32(from);
-}
-
-/* and imm32 to m32 */
-void AND32ItoM(u32 to, u32 from) {
- write8(0x81);
- ModRM(0, 0x4, DISP32);
- write32(to);
- write32(from);
-}
-
-/* and r32 to r32 */
-void AND32RtoR(int to, int from) {
- write8(0x21);
- ModRM(3, from, to);
-}
-
-/* and r32 to m32 */
-void AND32RtoM(u32 to, int from) {
- write8(0x21);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* and m32 to r32 */
-void AND32MtoR(int to, u32 from) {
- write8(0x23);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* not r32 */
-void NOT32R(int from) {
- write8(0xF7);
- ModRM(3, 2, from);
-}
-
-/* neg r32 */
-void NEG32R(int from) {
- write8(0xF7);
- ModRM(3, 3, from);
-}
-
-// jump instructions
-
-/* 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(int to) {
- write8(0xFF);
- ModRM(3, 4, to);
-}
-
-/* je rel8 */
-u8* JE8(u8 to) {
- J8Rel(0x74, to);
-}
-
-/* jz rel8 */
-u8* JZ8(u8 to) {
- J8Rel(0x74, to);
-}
-
-/* jg rel8 */
-u8* JG8(u8 to) {
- J8Rel(0x7F, to);
-}
-
-/* jge rel8 */
-u8* JGE8(u8 to) {
- J8Rel(0x7D, to);
-}
-
-/* jl rel8 */
-u8* JL8(u8 to) {
- J8Rel(0x7C, to);
-}
-
-/* jle rel8 */
-u8* JLE8(u8 to) {
- J8Rel(0x7E, to);
-}
-
-/* jne rel8 */
-u8* JNE8(u8 to) {
- J8Rel(0x75, to);
-}
-
-/* jnz rel8 */
-u8* JNZ8(u8 to) {
- J8Rel(0x75, to);
-}
-
-/* jng rel8 */
-u8* JNG8(u8 to) {
- J8Rel(0x7E, to);
-}
-
-/* jnge rel8 */
-u8* JNGE8(u8 to) {
- J8Rel(0x7C, to);
-}
-
-/* jnl rel8 */
-u8* JNL8(u8 to) {
- J8Rel(0x7D, to);
-}
-
-/* jnle rel8 */
-u8* JNLE8(u8 to) {
- J8Rel(0x7F, to);
-}
-
-/* jo rel8 */
-u8* JO8(u8 to) {
- J8Rel(0x70, to);
-}
-
-/* jno rel8 */
-u8* JNO8(u8 to) {
- J8Rel(0x71, to);
-}
-
-/* je rel32 */
-u32* JE32(u32 to) {
- J32Rel(0x84, to);
-}
-
-/* jz rel32 */
-u32* JZ32(u32 to) {
- J32Rel(0x84, to);
-}
-
-/* jg rel32 */
-u32* JG32(u32 to) {
- J32Rel(0x8F, to);
-}
-
-/* jge rel32 */
-u32* JGE32(u32 to) {
- J32Rel(0x8D, to);
-}
-
-/* jl rel32 */
-u32* JL32(u32 to) {
- J32Rel(0x8C, to);
-}
-
-/* jle rel32 */
-u32* JLE32(u32 to) {
- J32Rel(0x8E, to);
-}
-
-/* jne rel32 */
-u32* JNE32(u32 to) {
- J32Rel(0x85, to);
-}
-
-/* jnz rel32 */
-u32* JNZ32(u32 to) {
- J32Rel(0x85, to);
-}
-
-/* jng rel32 */
-u32* JNG32(u32 to) {
- J32Rel(0x8E, to);
-}
-
-/* jnge rel32 */
-u32* JNGE32(u32 to) {
- J32Rel(0x8C, to);
-}
-
-/* jnl rel32 */
-u32* JNL32(u32 to) {
- J32Rel(0x8D, to);
-}
-
-/* jnle rel32 */
-u32* JNLE32(u32 to) {
- J32Rel(0x8F, to);
-}
-
-/* jo rel32 */
-u32* JO32(u32 to) {
- J32Rel(0x80, to);
-}
-
-/* jno rel32 */
-u32* JNO32(u32 to) {
- J32Rel(0x81, 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(int to) {
- write8(0xFF);
- ModRM(3, 2, to);
-}
-
-/* call m32 */
-void CALL32M(u32 to) {
- write8(0xFF);
- ModRM(0, 2, DISP32);
- write32(to);
-}
-
-// misc instructions
-
-/* cmp imm32 to r32 */
-void CMP32ItoR(int 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(to);
- write32(from);
-}
-
-/* cmp r32 to r32 */
-void CMP32RtoR(int to, int from) {
- write8(0x39);
- ModRM(3, from, to);
-}
-
-/* cmp m32 to r32 */
-void CMP32MtoR(int to, u32 from) {
- write8(0x3B);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* test imm32 to r32 */
-void TEST32ItoR(int to, u32 from) {
- if (to == EAX) {
- write8(0xA9);
- } else {
- write8(0xF7);
- ModRM(3, 0, to);
- }
- write32(from);
-}
-
-/* test r32 to r32 */
-void TEST32RtoR(int to, int from) {
- write8(0x85);
- ModRM(3, from, to);
-}
-
-void BT32ItoR(int to,int from)
-{
- write16(0xba0f);
- write8(0xe0 | to);
- write8(from);
-}
-
-/* sets r8 */
-void SETS8R(int to) {
- SET8R(0x98, to);
-}
-/* setl r8 */
-void SETL8R(int to) {
- SET8R(0x9C, to);
-}
-
-/* setb r8 */
-void SETB8R(int to) {
- SET8R(0x92, to);
-}
-
-/* setnz r8 */
-void SETNZ8R(int to) {
- SET8R(0x95,to);
-}
-
-/* cbw */
-void CBW() {
- write16(0x9866);
-}
-
-/* cwd */
-void CWD() {
- write8(0x98);
-}
-
-/* cdq */
-void CDQ() {
- write8(0x99);
-}
-
-/* push r32 */
-void PUSH32R(int from) {
- write8(0x50 | from);
-}
-
-/* push m32 */
-void PUSH32M(u32 from) {
- write8(0xFF);
- ModRM(0, 6, DISP32);
- write32(from);
-}
-
-/* push imm32 */
-void PUSH32I(u32 from) {
- write8(0x68); write32(from);
-}
-
-/* pop r32 */
-void POP32R(int from) {
- write8(0x58 | from);
-}
-
-/* pushad */
-void PUSHA32() {
- write8(0x60);
-}
-
-/* popad */
-void POPA32() {
- write8(0x61);
-}
-
-/* ret */
-void RET() {
- write8(0xC3);
-}
-
-/********************/
-/* FPU instructions */
-/********************/
-
-//Added:basara 14.01.2003
-/* compare m32 to fpu reg stack */
-void FCOMP32(u32 from) {
- write8(0xD8);
- ModRM(0, 0x3, DISP32);
- write32(from);
-}
-
-void FNSTSWtoAX() {
- write16(0xE0DF);
-}
-
-/* fild m32 to fpu reg stack */
-void FILD32(u32 from) {
- write8(0xDB);
- ModRM(0, 0x0, DISP32);
- write32(from);
-}
-
-/* fistp m32 from fpu reg stack */
-void FISTP32(u32 from) {
- write8(0xDB);
- ModRM(0, 0x3, DISP32);
- write32(from);
-}
-
-/* fld m32 to fpu reg stack */
-void FLD32(u32 from) {
- write8(0xD9);
- ModRM(0, 0x0, DISP32);
- write32(from);
-}
-
-/* fstp m32 from fpu reg stack */
-void FSTP32(u32 to) {
- write8(0xD9);
- ModRM(0, 0x3, DISP32);
- write32(to);
-}
-
-//
-
-/* fldcw fpu control word from m16 */
-void FLDCW(u32 from) {
- write8(0xD9);
- ModRM(0, 0x5, DISP32);
- write32(from);
-}
-
-/* fnstcw fpu control word to m16 */
-void FNSTCW(u32 to) {
- write8(0xD9);
- ModRM(0, 0x7, DISP32);
- write32(to);
-}
-
-//
-
-/* fadd m32 to fpu reg stack */
-void FADD32(u32 from) {
- write8(0xD8);
- ModRM(0, 0x0, DISP32);
- write32(from);
-}
-
-/* fsub m32 to fpu reg stack */
-void FSUB32(u32 from) {
- write8(0xD8);
- ModRM(0, 0x4, DISP32);
- write32(from);
-}
-
-/* fmul m32 to fpu reg stack */
-void FMUL32(u32 from) {
- write8(0xD8);
- ModRM(0, 0x1, DISP32);
- write32(from);
-}
-
-/* fdiv m32 to fpu reg stack */
-void FDIV32(u32 from) {
- write8(0xD8);
- ModRM(0, 0x6, DISP32);
- write32(from);
-}
-
-/* fabs fpu reg stack */
-void FABS() {
- write16(0xE1D9);
-}
-
-/* fsqrt fpu reg stack */
-void FSQRT() {
- write16(0xFAD9);
-}
-
-/* fchs fpu reg stack */
-void FCHS() {
- write16(0xE0D9);
-}
-
-/********************/
-/* MMX instructions */
-/********************/
-
-// r64 = mm
-
-/* movq m64 to r64 */
-void MOVQMtoR(int to, u32 from) {
- write16(0x6F0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* movq r64 to m64 */
-void MOVQRtoM(u32 to, int from) {
- write16(0x7F0F);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* pand r64 to r64 */
-void PANDRtoR(int to, int from) {
- write16(0xDB0F);
- ModRM(3, to, from);
-}
-
-/* pand r64 to r64 */
-void PANDNRtoR(int to, int from) {
- write16(0xDF0F);
- ModRM(3, to, from);
-}
-
-/* por r64 to r64 */
-void PORRtoR(int to, int from) {
- write16(0xEB0F);
- ModRM(3, to, from);
-}
-
-/* pxor r64 to r64 */
-void PXORRtoR(int to, int from) {
- write16(0xEF0F);
- ModRM(3, to, from);
-}
-
-/* psllq r64 to r64 */
-void PSLLQRtoR(int to, int from) {
- write16(0xF30F);
- ModRM(3, to, from);
-}
-
-/* psllq m64 to r64 */
-void PSLLQMtoR(int to, u32 from) {
- write16(0xF30F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* psllq imm8 to r64 */
-void PSLLQItoR(int to, u8 from) {
- write16(0x730F);
- ModRM(3, 6, to);
- write8(from);
-}
-
-/* psrlq r64 to r64 */
-void PSRLQRtoR(int to, int from) {
- write16(0xD30F);
- ModRM(3, to, from);
-}
-
-/* psrlq m64 to r64 */
-void PSRLQMtoR(int to, u32 from) {
- write16(0xD30F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* psrlq imm8 to r64 */
-void PSRLQItoR(int to, u8 from) {
- write16(0x730F);
- ModRM(3, 2, to);
- write8(from);
-}
-
-/* paddusb r64 to r64 */
-void PADDUSBRtoR(int to, int from) {
- write16(0xDC0F);
- ModRM(3, to, from);
-}
-
-/* paddusb m64 to r64 */
-void PADDUSBMtoR(int to, u32 from) {
- write16(0xDC0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* paddusw r64 to r64 */
-void PADDUSWRtoR(int to, int from) {
- write16(0xDD0F);
- ModRM(3, to, from);
-}
-
-/* paddusw m64 to r64 */
-void PADDUSWMtoR(int to, u32 from) {
- write16(0xDD0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* paddb r64 to r64 */
-void PADDBRtoR(int to, int from) {
- write16(0xFC0F);
- ModRM(3, to, from);
-}
-
-/* paddb m64 to r64 */
-void PADDBMtoR(int to, u32 from) {
- write16(0xFC0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* paddw r64 to r64 */
-void PADDWRtoR(int to, int from) {
- write16(0xFD0F);
- ModRM(3, to, from);
-}
-
-/* paddw m64 to r64 */
-void PADDWMtoR(int to, u32 from) {
- write16(0xFD0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* paddd r64 to r64 */
-void PADDDRtoR(int to, int from) {
- write16(0xFE0F);
- ModRM(3, to, from);
-}
-
-/* paddd m64 to r64 */
-void PADDDMtoR(int to, u32 from) {
- write16(0xFE0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* emms */
-void EMMS() {
- //use femms if we have 3dnow
- write16(0x0e0f);
- return;
-}
-
-/* femms */
-void FEMMS() {
- write16(0x770F);
- return;
-}
-
-//Basara:changed
-void PADDSBRtoR(int to, int from) {
- write16(0xEC0F);
- ModRM(3, to, from);
-}
-
-void PADDSWRtoR(int to, int from) {
- write16(0xED0F);
- ModRM(3, to, from);
-}
-
-void PADDSDRtoR(int to, int from) {
- write16(0xEE0F);
- ModRM(3, to, from);
-}
-
-void PSUBSBRtoR(int to, int from) {
- write16(0xE80F);
- ModRM(3, to, from);
-}
-
-void PSUBSWRtoR(int to, int from) {
- write16(0xE90F);
- ModRM(3, to, from);
-}
-
-void PSUBSDRtoR(int to, int from) {
- write16(0xEA0F);
- ModRM(3, to, from);
-}
-
-void PSUBBRtoR(int to, int from) {
- write16(0xF80F);
- ModRM(3, to, from);
-}
-
-void PSUBWRtoR(int to, int from) {
- write16(0xF90F);
- ModRM(3, to, from);
-}
-
-void PSUBDRtoR(int to, int from) {
- write16(0xFA0F);
- ModRM(3, to, from);
-}
-
-//changed:basara
-//P.s.It's sux.Don't use it offten.
-void MOVQ64ItoR(int reg,u64 i)
-{
- MOVQMtoR(reg,(u32)(x86Ptr)+2+7);
- JMP8(8);
- write64(i);
-}
-
-void PSUBUSBRtoR(int to, int from) {
- write16(0xD80F);
- ModRM(3, to, from);
-}
-
-void PSUBUSWRtoR(int to, int from) {
- write16(0xD90F);
- ModRM(3, to, from);
-}
-
-void PMAXSWRtoR(int to,int from)
-{
- write16(0xEE0F);
- ModRM(3, to, from);
-}
-
-void PMINSWRtoR(int to,int from)
-{
- write16(0xEA0F);
- ModRM(3, to, from);
-}
-
-void PCMPEQBRtoR(int to,int from)
-{
- write16(0x740F);
- ModRM(3, to, from);
-}
-
-void PCMPEQWRtoR(int to,int from)
-{
- write16(0x750F);
- ModRM(3, to, from);
-}
-
-void PCMPEQDRtoR(int to,int from)
-{
- write16(0x760F);
- ModRM(3, to, from);
-}
-
-void PCMPGTBRtoR(int to,int from)
-{
- write16(0x640F);
- ModRM(3, to, from);
-}
-
-void PCMPGTWRtoR(int to,int from)
-{
- write16(0x650F);
- ModRM(3, to, from);
-}
-
-void PCMPGTDRtoR(int to,int from)
-{
- write16(0x660F);
- ModRM(3, to, from);
-}
-
-//Basara:Added 10.01.2003
-void PSRLWItoR(int to,int from)
-{
- write16(0x710f);
- ModRM(2, 2 , to);
- write8(from);
-}
-void PSRLDItoR(int to,int from)
-{
- write16(0x720f);
- ModRM(2, 2 , to);
- write8(from);
-}
-
-void PSLLWItoR(int to,int from)
-{
- write16(0x710f);
- ModRM(3, 6 , to);
- write8(from);
-}
-
-void PSLLDItoR(int to,int from)
-{
- write16(0x720f);
- ModRM(3, 6 , to);
- write8(from);
-}
-
-void PSRAWItoR(int to,int from)
-{
- write16(0x710f);
- ModRM(3, 4 , to);
- write8(from);
-}
-
-void PSRADItoR(int to,int from)
-{
- write16(0x720f);
- ModRM(3, 4 , to);
- write8(from);
-}
-
-/* por m64 to r64 */
-void PORMtoR(int to, u32 from) {
- write16(0xEB0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* pxor m64 to r64 */
-void PXORMtoR(int to, u32 from) {
- write16(0xEF0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* pand m64 to r64 */
-void PANDMtoR(int to, u32 from) {
- write16(0xDB0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* pandn m64 to r64 */
-void PANDNMtoR(int to, u32 from) {
- write16(0xDF0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* movd m32 to r64 */
-void MOVDMtoR(int to, u32 from) {
- write16(0x6E0F);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-/* movq r64 to m32 */
-void MOVDRtoM(u32 to, int from) {
- write16(0x7E0F);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-/* movd r32 to r64 */
-void MOVD32RtoR(int to, int from) {
- write16(0x6E0F);
- ModRM(3, to,from);
-}
-
-/* movq r64 to r32 */
-void MOVD64RtoR(int to, int from) {
- write16(0x7E0F);
- ModRM(3, from,to);
-}
-
-void MOVQRtoR(int to, int from) {
- write16(0x6F0F);
- ModRM(3, to,from);
-}
-
-void PUNPCKHDQRtoR(int to, int from) {
- write16(0x6A0F);
- ModRM(3, to,from);
-}
-
-void PUNPCKLDQRtoR(int to, int from) {
- write16(0x620F);
- ModRM(3, to,from);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// SSE intructions
-//////////////////////////////////////////////////////////////////////////
-
-void MOVAPSMtoR(int to, int from) {
- write16(0x280f);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-void MOVAPSRtoM(int to, int from) {
- write16(0x2b0f);
- ModRM(0, from, DISP32);
- write32(to);
-}
-
-void MOVAPSRtoR(int to, int from) {
- write16(0x290f);
- ModRM(3, to,from);
-}
-
-void ORPSMtoR(int to, int from) {
- write16(0x560f);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-void ORPSRtoR(int to, int from) {
- write16(0x560f);
- ModRM(3, to,from);
-}
-
-void XORPSMtoR(int to, int from) {
- write16(0x570f);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-void XORPSRtoR(int to, int from) {
- write16(0x570f);
- ModRM(3, to,from);
-}
-
-void ANDPSMtoR(int to, int from) {
- write16(0x540f);
- ModRM(0, to, DISP32);
- write32(from);
-}
-
-void ANDPSRtoR(int to, int from) {
- write16(0x540f);
- ModRM(3, to,from);
-}
-
-/*
- 3DNOW intructions
-*/
-
-void PFCMPEQMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0xb0);
-}
-
-void PFCMPGTMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0xa0);
-}
-
-void PFCMPGEMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x90);
-}
-
-void PFADDMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x9e);
-}
-
-void PFADDRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to, from);
- write8(0x9e);
-}
-
-void PFSUBMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x9a);
-}
-
-void PFSUBRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to, from);
- write8(0x9a);
-}
-
-void PFMULMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0xb4);
-}
-
-void PFMULRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to,from);
- write8(0xb4);
-}
-
-void PFRCPMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x96);
-}
-
-void PFRCPRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to,from);
- write8(0x96);
-}
-
-void PFRCPIT1RtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to,from);
- write8(0xa6);
-}
-
-void PFRCPIT2RtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to,from);
- write8(0xb6);
-}
-
-void PFRSQRTRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to,from);
- write8(0x97);
-}
-
-void PFRSQIT1RtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to,from);
- write8(0xa7);
-}
-
-void PF2IDMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x1d);
-}
-
-void PF2IDRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to, from);
- write8(0x1d);
-}
-
-void PI2FDMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x0d);
-}
-
-void PI2FDRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to, from);
- write8(0x0d);
-}
-
-/*
- 3DNOW Extension intructions
-*/
-
-void PFMAXMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0xa4);
-}
-
-void PFMAXRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to, from);
- write8(0xa4);
-}
-
-void PFMINMtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(0, to, DISP32);
- write32(from);
- write8(0x94);
-}
-
-void PFMINRtoR(int to, int from) {
- write16(0x0f0f);
- ModRM(3, to, from);
- write8(0x94);
-}
-
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* + * ix86 core v0.5.1 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + */ + +#ifdef __i386__ + +#include "ix86.h" + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +void x86Init() { +} + +void x86SetPtr(char *ptr) { + x86Ptr = ptr; +} + +void x86Shutdown() { +} + +void x86SetJ8(u8 *j8) { + u32 jump = (x86Ptr - (s8*)j8) - 1; + + if (jump > 0x7f) printf("j8 greater than 0x7f!!\n"); + *j8 = (u8)jump; +} + +void x86SetJ32(u32 *j32) { + *j32 = (x86Ptr - (s8*)j32) - 4; +} + +void x86Align(int bytes) { + // fordward align + x86Ptr = (s8*)(((u32)x86Ptr + bytes) & ~(bytes - 1)); +} + +#define SIB 4 +#define DISP32 5 + +/* macros helpers */ + +#define ModRM(mod, rm, reg) \ + write8((mod << 6) | (rm << 3) | (reg)); + +#define SibSB(ss, rm, index) \ + write8((ss << 6) | (rm << 3) | (index)); + +#define SET8R(cc, to) { \ + write8(0x0F); write8(cc); \ + write8((0xC0) | (to)); } + +#define J8Rel(cc, to) { \ + write8(cc); write8(to); return x86Ptr - 1; } + +#define J32Rel(cc, to) { \ + write8(0x0F); write8(cc); write32(to); return (u32*)(x86Ptr - 4); } + +#define CMOV32RtoR(cc, to, from) { \ + write8(0x0F); write8(cc); \ + ModRM(3, to, from); } + +#define CMOV32MtoR(cc, to, from) { \ + write8(0x0F); write8(cc); \ + ModRM(0, to, DISP32); \ + write32(from); } + +/********************/ +/* IX86 intructions */ +/********************/ + +// mov instructions + +/* mov r32 to r32 */ +void MOV32RtoR(int to, int from) { + write8(0x89); + ModRM(3, from, to); +} + +/* mov r32 to m32 */ +void MOV32RtoM(u32 to, int from) { + write8(0x89); + ModRM(0, from, DISP32); + write32(to); +} + +/* mov m32 to r32 */ +void MOV32MtoR(int to, u32 from) { + write8(0x8B); + ModRM(0, to, DISP32); + write32(from); +} + +/* mov [r32] to r32 */ +void MOV32RmtoR(int to, int from) { + write8(0x8B); + ModRM(0, to, from); +} + +/* mov [r32][r32*scale] to r32 */ +void MOV32RmStoR(int to, int from, int from2, int scale) { + write8(0x8B); + ModRM(0, to, 0x4); + SibSB(scale, from2, from); +} + +/* mov r32 to [r32] */ +void MOV32RtoRm(int to, int from) { + write8(0x89); + ModRM(0, from, to); +} + +/* mov r32 to [r32][r32*scale] */ +void MOV32RtoRmS(int to, int to2, int scale, int from) { + write8(0x89); + ModRM(0, from, 0x4); + SibSB(scale, to2, to); +} + +/* mov imm32 to r32 */ +void MOV32ItoR(int to, u32 from) { + write8(0xB8 | to); + write32(from); +} + +/* mov imm32 to m32 */ +void MOV32ItoM(u32 to, u32 from) { + write8(0xC7); + ModRM(0, 0, DISP32); + write32(to); + write32(from); +} + +/* mov r16 to m16 */ +void MOV16RtoM(u32 to, int from) { + write8(0x66); + write8(0x89); + ModRM(0, from, DISP32); + write32(to); +} + +/* mov m16 to r16 */ +void MOV16MtoR(int to, u32 from) { + write8(0x66); + write8(0x8B); + ModRM(0, to, DISP32); + write32(from); +} + +/* mov imm16 to m16 */ +void MOV16ItoM(u32 to, u16 from) { + write8(0x66); + write8(0xC7); + ModRM(0, 0, DISP32); + write32(to); + write16(from); +} + +/* mov r8 to m8 */ +void MOV8RtoM(u32 to, int from) { + write8(0x88); + ModRM(0, from, DISP32); + write32(to); +} + +/* mov m8 to r8 */ +void MOV8MtoR(int to, u32 from) { + write8(0x8A); + ModRM(0, to, DISP32); + write32(from); +} + +/* mov imm8 to m8 */ +void MOV8ItoM(u32 to, u8 from) { + write8(0xC6); + ModRM(0, 0, DISP32); + write32(to); + write8(from); +} + +/* movsx r8 to r32 */ +void MOVSX32R8toR(int to, int from) { + write16(0xBE0F); + ModRM(3, to, from); +} + +/* movsx m8 to r32 */ +void MOVSX32M8toR(int to, u32 from) { + write16(0xBE0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* movsx r16 to r32 */ +void MOVSX32R16toR(int to, int from) { + write16(0xBF0F); + ModRM(3, to, from); +} + +/* movsx m16 to r32 */ +void MOVSX32M16toR(int to, u32 from) { + write16(0xBF0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* movzx r8 to r32 */ +void MOVZX32R8toR(int to, int from) { + write16(0xB60F); + ModRM(3, to, from); +} + +/* movzx m8 to r32 */ +void MOVZX32M8toR(int to, u32 from) { + write16(0xB60F); + ModRM(0, to, DISP32); + write32(from); +} + +/* movzx r16 to r32 */ +void MOVZX32R16toR(int to, int from) { + write16(0xB70F); + ModRM(3, to, from); +} + +/* movzx m16 to r32 */ +void MOVZX32M16toR(int to, u32 from) { + write16(0xB70F); + ModRM(0, to, DISP32); + write32(from); +} + +/* cmovne r32 to r32 */ +void CMOVNE32RtoR(int to, int from) { + CMOV32RtoR(0x45, to, from); +} + +/* cmovne m32 to r32*/ +void CMOVNE32MtoR(int to, u32 from) { + CMOV32MtoR(0x45, to, from); +} + +/* cmove r32 to r32*/ +void CMOVE32RtoR(int to, int from) { + CMOV32RtoR(0x44, to, from); +} + +/* cmove m32 to r32*/ +void CMOVE32MtoR(int to, u32 from) { + CMOV32MtoR(0x44, to, from); +} + +/* cmovg r32 to r32*/ +void CMOVG32RtoR(int to, int from) { + CMOV32RtoR(0x4F, to, from); +} + +/* cmovg m32 to r32*/ +void CMOVG32MtoR(int to, u32 from) { + CMOV32MtoR(0x4F, to, from); +} + +/* cmovge r32 to r32*/ +void CMOVGE32RtoR(int to, int from) { + CMOV32RtoR(0x4D, to, from); +} + +/* cmovge m32 to r32*/ +void CMOVGE32MtoR(int to, u32 from) { + CMOV32MtoR(0x4D, to, from); +} + +/* cmovl r32 to r32*/ +void CMOVL32RtoR(int to, int from) { + CMOV32RtoR(0x4C, to, from); +} + +/* cmovl m32 to r32*/ +void CMOVL32MtoR(int to, u32 from) { + CMOV32MtoR(0x4C, to, from); +} + +/* cmovle r32 to r32*/ +void CMOVLE32RtoR(int to, int from) { + CMOV32RtoR(0x4E, to, from); +} + +/* cmovle m32 to r32*/ +void CMOVLE32MtoR(int to, u32 from) { + CMOV32MtoR(0x4E, to, from); +} + +// arithmic instructions + +/* add imm32 to r32 */ +void ADD32ItoR(int to, u32 from) { + 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(to); + write32(from); +} + +/* add r32 to r32 */ +void ADD32RtoR(int to, int from) { + write8(0x01); + ModRM(3, from, to); +} + +/* add r32 to m32 */ +void ADD32RtoM(u32 to, int from) { + write8(0x01); + ModRM(0, from, DISP32); + write32(to); +} + +/* add m32 to r32 */ +void ADD32MtoR(int to, u32 from) { + write8(0x03); + ModRM(0, to, DISP32); + write32(from); +} + +/* adc imm32 to r32 */ +void ADC32ItoR(int to, u32 from) { + if (to == EAX) { + write8(0x15); + } else { + write8(0x81); + ModRM(3, 2, to); + } + write32(from); +} + +/* adc r32 to r32 */ +void ADC32RtoR(int to, int from) { + write8(0x11); + ModRM(3, from, to); +} + +/* adc m32 to r32 */ +void ADC32MtoR(int to, u32 from) { + write8(0x13); + ModRM(0, to, DISP32); + write32(from); +} + +/* inc r32 */ +void INC32R(int to) { + write8(0x40 + to); +} + +/* inc m32 */ +void INC32M(u32 to) { + write8(0xFF); + ModRM(0, 0, DISP32); + write32(to); +} + +/* sub imm32 to r32 */ +void SUB32ItoR(int to, u32 from) { + if (to == EAX) { + write8(0x2D); + } else { + write8(0x81); + ModRM(3, 5, to); + } + write32(from); +} + +/* sub r32 to r32 */ +void SUB32RtoR(int to, int from) { + write8(0x29); + ModRM(3, from, to); +} + +/* sub m32 to r32 */ +void SUB32MtoR(int to, u32 from) { + write8(0x2B); + ModRM(0, to, DISP32); + write32(from); +} + +/* sbb imm32 to r32 */ +void SBB32ItoR(int to, u32 from) { + if (to == EAX) { + write8(0x1D); + } else { + write8(0x81); + ModRM(3, 3, to); + } + write32(from); +} + +/* sbb r32 to r32 */ +void SBB32RtoR(int to, int from) { + write8(0x19); + ModRM(3, from, to); +} + +/* sbb m32 to r32 */ +void SBB32MtoR(int to, u32 from) { + write8(0x1B); + ModRM(0, to, DISP32); + write32(from); +} + +/* dec r32 */ +void DEC32R(int to) { + write8(0x48 + to); +} + +/* dec m32 */ +void DEC32M(u32 to) { + write8(0xFF); + ModRM(0, 1, DISP32); + write32(to); +} + +/* mul eax by r32 to edx:eax */ +void MUL32R(int from) { + write8(0xF7); + ModRM(3, 4, from); +} + +/* imul eax by r32 to edx:eax */ +void IMUL32R(int 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(from); +} + +/* imul eax by m32 to edx:eax */ +void IMUL32M(u32 from) { + write8(0xF7); + ModRM(0, 5, DISP32); + write32(from); +} + +/* imul r32 by r32 to r32 */ +void IMUL32RtoR(int to, int from) { + write16(0xAF0F); + ModRM(3, to, from); +} + +/* div eax by r32 to edx:eax */ +void DIV32R(int from) { + write8(0xF7); + ModRM(3, 6, from); +} + +/* idiv eax by r32 to edx:eax */ +void IDIV32R(int 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(from); +} + +/* idiv eax by m32 to edx:eax */ +void IDIV32M(u32 from) { + write8(0xF7); + ModRM(0, 7, DISP32); + write32(from); +} + +// shifting instructions + +void RCR32ItoR(int to,int from) +{ + if (from==1) + { + write8(0xd1); + write8(0xd8 | to); + } + else + { + write8(0xc1); + write8(0xd8 | to); + write8(from); + } +} + +/* shl imm8 to r32 */ +void SHL32ItoR(int to, u8 from) { + if (from==1) + { + write8(0xd1); + write8(0xe0 | to); + return; + } + write8(0xC1); + ModRM(3, 4, to); + write8(from); +} + +/* shl cl to r32 */ +void SHL32CLtoR(int to) { + write8(0xD3); + ModRM(3, 4, to); +} + +/* shr imm8 to r32 */ +void SHR32ItoR(int to, u8 from) { + if (from==1) + { + write8(0xd1); + write8(0xe8 | to); + return; + } + write8(0xC1); + ModRM(3, 5, to); + write8(from); +} + +/* shr cl to r32 */ +void SHR32CLtoR(int to) { + write8(0xD3); + ModRM(3, 5, to); +} + +/* sar imm8 to r32 */ +void SAR32ItoR(int to, u8 from) { + write8(0xC1); + ModRM(3, 7, to); + write8(from); +} + +/* sar cl to r32 */ +void SAR32CLtoR(int to) { + write8(0xD3); + ModRM(3, 7, to); +} + + +// logical instructions + +/* or imm32 to r32 */ +void OR32ItoR(int 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(to); + write32(from); +} + +/* or r32 to r32 */ +void OR32RtoR(int to, int from) { + write8(0x09); + ModRM(3, from, to); +} + +/* or r32 to m32 */ +void OR32RtoM(u32 to, int from) { + write8(0x09); + ModRM(0, from, DISP32); + write32(to); +} + +/* or m32 to r32 */ +void OR32MtoR(int to, u32 from) { + write8(0x0B); + ModRM(0, to, DISP32); + write32(from); +} + +/* xor imm32 to r32 */ +void XOR32ItoR(int 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(to); + write32(from); +} + +/* xor r32 to r32 */ +void XOR32RtoR(int to, int from) { + write8(0x31); + ModRM(3, from, to); +} + +/* xor r32 to m32 */ +void XOR32RtoM(u32 to, int from) { + write8(0x31); + ModRM(0, from, DISP32); + write32(to); +} + +/* xor m32 to r32 */ +void XOR32MtoR(int to, u32 from) { + write8(0x33); + ModRM(0, to, DISP32); + write32(from); +} + +/* and imm32 to r32 */ +void AND32ItoR(int to, u32 from) { + if (to == EAX) { + write8(0x25); + } else { + write8(0x81); + ModRM(3, 0x4, to); + } + write32(from); +} + +/* and imm32 to m32 */ +void AND32ItoM(u32 to, u32 from) { + write8(0x81); + ModRM(0, 0x4, DISP32); + write32(to); + write32(from); +} + +/* and r32 to r32 */ +void AND32RtoR(int to, int from) { + write8(0x21); + ModRM(3, from, to); +} + +/* and r32 to m32 */ +void AND32RtoM(u32 to, int from) { + write8(0x21); + ModRM(0, from, DISP32); + write32(to); +} + +/* and m32 to r32 */ +void AND32MtoR(int to, u32 from) { + write8(0x23); + ModRM(0, to, DISP32); + write32(from); +} + +/* not r32 */ +void NOT32R(int from) { + write8(0xF7); + ModRM(3, 2, from); +} + +/* neg r32 */ +void NEG32R(int from) { + write8(0xF7); + ModRM(3, 3, from); +} + +// jump instructions + +/* 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(int to) { + write8(0xFF); + ModRM(3, 4, to); +} + +/* je rel8 */ +u8* JE8(u8 to) { + J8Rel(0x74, to); +} + +/* jz rel8 */ +u8* JZ8(u8 to) { + J8Rel(0x74, to); +} + +/* jg rel8 */ +u8* JG8(u8 to) { + J8Rel(0x7F, to); +} + +/* jge rel8 */ +u8* JGE8(u8 to) { + J8Rel(0x7D, to); +} + +/* jl rel8 */ +u8* JL8(u8 to) { + J8Rel(0x7C, to); +} + +/* jle rel8 */ +u8* JLE8(u8 to) { + J8Rel(0x7E, to); +} + +/* jne rel8 */ +u8* JNE8(u8 to) { + J8Rel(0x75, to); +} + +/* jnz rel8 */ +u8* JNZ8(u8 to) { + J8Rel(0x75, to); +} + +/* jng rel8 */ +u8* JNG8(u8 to) { + J8Rel(0x7E, to); +} + +/* jnge rel8 */ +u8* JNGE8(u8 to) { + J8Rel(0x7C, to); +} + +/* jnl rel8 */ +u8* JNL8(u8 to) { + J8Rel(0x7D, to); +} + +/* jnle rel8 */ +u8* JNLE8(u8 to) { + J8Rel(0x7F, to); +} + +/* jo rel8 */ +u8* JO8(u8 to) { + J8Rel(0x70, to); +} + +/* jno rel8 */ +u8* JNO8(u8 to) { + J8Rel(0x71, to); +} + +/* je rel32 */ +u32* JE32(u32 to) { + J32Rel(0x84, to); +} + +/* jz rel32 */ +u32* JZ32(u32 to) { + J32Rel(0x84, to); +} + +/* jg rel32 */ +u32* JG32(u32 to) { + J32Rel(0x8F, to); +} + +/* jge rel32 */ +u32* JGE32(u32 to) { + J32Rel(0x8D, to); +} + +/* jl rel32 */ +u32* JL32(u32 to) { + J32Rel(0x8C, to); +} + +/* jle rel32 */ +u32* JLE32(u32 to) { + J32Rel(0x8E, to); +} + +/* jne rel32 */ +u32* JNE32(u32 to) { + J32Rel(0x85, to); +} + +/* jnz rel32 */ +u32* JNZ32(u32 to) { + J32Rel(0x85, to); +} + +/* jng rel32 */ +u32* JNG32(u32 to) { + J32Rel(0x8E, to); +} + +/* jnge rel32 */ +u32* JNGE32(u32 to) { + J32Rel(0x8C, to); +} + +/* jnl rel32 */ +u32* JNL32(u32 to) { + J32Rel(0x8D, to); +} + +/* jnle rel32 */ +u32* JNLE32(u32 to) { + J32Rel(0x8F, to); +} + +/* jo rel32 */ +u32* JO32(u32 to) { + J32Rel(0x80, to); +} + +/* jno rel32 */ +u32* JNO32(u32 to) { + J32Rel(0x81, 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(int to) { + write8(0xFF); + ModRM(3, 2, to); +} + +/* call m32 */ +void CALL32M(u32 to) { + write8(0xFF); + ModRM(0, 2, DISP32); + write32(to); +} + +// misc instructions + +/* cmp imm32 to r32 */ +void CMP32ItoR(int 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(to); + write32(from); +} + +/* cmp r32 to r32 */ +void CMP32RtoR(int to, int from) { + write8(0x39); + ModRM(3, from, to); +} + +/* cmp m32 to r32 */ +void CMP32MtoR(int to, u32 from) { + write8(0x3B); + ModRM(0, to, DISP32); + write32(from); +} + +/* test imm32 to r32 */ +void TEST32ItoR(int to, u32 from) { + if (to == EAX) { + write8(0xA9); + } else { + write8(0xF7); + ModRM(3, 0, to); + } + write32(from); +} + +/* test r32 to r32 */ +void TEST32RtoR(int to, int from) { + write8(0x85); + ModRM(3, from, to); +} + +void BT32ItoR(int to,int from) +{ + write16(0xba0f); + write8(0xe0 | to); + write8(from); +} + +/* sets r8 */ +void SETS8R(int to) { + SET8R(0x98, to); +} +/* setl r8 */ +void SETL8R(int to) { + SET8R(0x9C, to); +} + +/* setb r8 */ +void SETB8R(int to) { + SET8R(0x92, to); +} + +/* setnz r8 */ +void SETNZ8R(int to) { + SET8R(0x95,to); +} + +/* cbw */ +void CBW() { + write16(0x9866); +} + +/* cwd */ +void CWD() { + write8(0x98); +} + +/* cdq */ +void CDQ() { + write8(0x99); +} + +/* push r32 */ +void PUSH32R(int from) { + write8(0x50 | from); +} + +/* push m32 */ +void PUSH32M(u32 from) { + write8(0xFF); + ModRM(0, 6, DISP32); + write32(from); +} + +/* push imm32 */ +void PUSH32I(u32 from) { + write8(0x68); write32(from); +} + +/* pop r32 */ +void POP32R(int from) { + write8(0x58 | from); +} + +/* pushad */ +void PUSHA32() { + write8(0x60); +} + +/* popad */ +void POPA32() { + write8(0x61); +} + +/* ret */ +void RET() { + write8(0xC3); +} + +/********************/ +/* FPU instructions */ +/********************/ + +//Added:basara 14.01.2003 +/* compare m32 to fpu reg stack */ +void FCOMP32(u32 from) { + write8(0xD8); + ModRM(0, 0x3, DISP32); + write32(from); +} + +void FNSTSWtoAX() { + write16(0xE0DF); +} + +/* fild m32 to fpu reg stack */ +void FILD32(u32 from) { + write8(0xDB); + ModRM(0, 0x0, DISP32); + write32(from); +} + +/* fistp m32 from fpu reg stack */ +void FISTP32(u32 from) { + write8(0xDB); + ModRM(0, 0x3, DISP32); + write32(from); +} + +/* fld m32 to fpu reg stack */ +void FLD32(u32 from) { + write8(0xD9); + ModRM(0, 0x0, DISP32); + write32(from); +} + +/* fstp m32 from fpu reg stack */ +void FSTP32(u32 to) { + write8(0xD9); + ModRM(0, 0x3, DISP32); + write32(to); +} + +// + +/* fldcw fpu control word from m16 */ +void FLDCW(u32 from) { + write8(0xD9); + ModRM(0, 0x5, DISP32); + write32(from); +} + +/* fnstcw fpu control word to m16 */ +void FNSTCW(u32 to) { + write8(0xD9); + ModRM(0, 0x7, DISP32); + write32(to); +} + +// + +/* fadd m32 to fpu reg stack */ +void FADD32(u32 from) { + write8(0xD8); + ModRM(0, 0x0, DISP32); + write32(from); +} + +/* fsub m32 to fpu reg stack */ +void FSUB32(u32 from) { + write8(0xD8); + ModRM(0, 0x4, DISP32); + write32(from); +} + +/* fmul m32 to fpu reg stack */ +void FMUL32(u32 from) { + write8(0xD8); + ModRM(0, 0x1, DISP32); + write32(from); +} + +/* fdiv m32 to fpu reg stack */ +void FDIV32(u32 from) { + write8(0xD8); + ModRM(0, 0x6, DISP32); + write32(from); +} + +/* fabs fpu reg stack */ +void FABS() { + write16(0xE1D9); +} + +/* fsqrt fpu reg stack */ +void FSQRT() { + write16(0xFAD9); +} + +/* fchs fpu reg stack */ +void FCHS() { + write16(0xE0D9); +} + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR(int to, u32 from) { + write16(0x6F0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* movq r64 to m64 */ +void MOVQRtoM(u32 to, int from) { + write16(0x7F0F); + ModRM(0, from, DISP32); + write32(to); +} + +/* pand r64 to r64 */ +void PANDRtoR(int to, int from) { + write16(0xDB0F); + ModRM(3, to, from); +} + +/* pand r64 to r64 */ +void PANDNRtoR(int to, int from) { + write16(0xDF0F); + ModRM(3, to, from); +} + +/* por r64 to r64 */ +void PORRtoR(int to, int from) { + write16(0xEB0F); + ModRM(3, to, from); +} + +/* pxor r64 to r64 */ +void PXORRtoR(int to, int from) { + write16(0xEF0F); + ModRM(3, to, from); +} + +/* psllq r64 to r64 */ +void PSLLQRtoR(int to, int from) { + write16(0xF30F); + ModRM(3, to, from); +} + +/* psllq m64 to r64 */ +void PSLLQMtoR(int to, u32 from) { + write16(0xF30F); + ModRM(0, to, DISP32); + write32(from); +} + +/* psllq imm8 to r64 */ +void PSLLQItoR(int to, u8 from) { + write16(0x730F); + ModRM(3, 6, to); + write8(from); +} + +/* psrlq r64 to r64 */ +void PSRLQRtoR(int to, int from) { + write16(0xD30F); + ModRM(3, to, from); +} + +/* psrlq m64 to r64 */ +void PSRLQMtoR(int to, u32 from) { + write16(0xD30F); + ModRM(0, to, DISP32); + write32(from); +} + +/* psrlq imm8 to r64 */ +void PSRLQItoR(int to, u8 from) { + write16(0x730F); + ModRM(3, 2, to); + write8(from); +} + +/* paddusb r64 to r64 */ +void PADDUSBRtoR(int to, int from) { + write16(0xDC0F); + ModRM(3, to, from); +} + +/* paddusb m64 to r64 */ +void PADDUSBMtoR(int to, u32 from) { + write16(0xDC0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* paddusw r64 to r64 */ +void PADDUSWRtoR(int to, int from) { + write16(0xDD0F); + ModRM(3, to, from); +} + +/* paddusw m64 to r64 */ +void PADDUSWMtoR(int to, u32 from) { + write16(0xDD0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* paddb r64 to r64 */ +void PADDBRtoR(int to, int from) { + write16(0xFC0F); + ModRM(3, to, from); +} + +/* paddb m64 to r64 */ +void PADDBMtoR(int to, u32 from) { + write16(0xFC0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* paddw r64 to r64 */ +void PADDWRtoR(int to, int from) { + write16(0xFD0F); + ModRM(3, to, from); +} + +/* paddw m64 to r64 */ +void PADDWMtoR(int to, u32 from) { + write16(0xFD0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* paddd r64 to r64 */ +void PADDDRtoR(int to, int from) { + write16(0xFE0F); + ModRM(3, to, from); +} + +/* paddd m64 to r64 */ +void PADDDMtoR(int to, u32 from) { + write16(0xFE0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* emms */ +void EMMS() { + //use femms if we have 3dnow + write16(0x0e0f); + return; +} + +/* femms */ +void FEMMS() { + write16(0x770F); + return; +} + +//Basara:changed +void PADDSBRtoR(int to, int from) { + write16(0xEC0F); + ModRM(3, to, from); +} + +void PADDSWRtoR(int to, int from) { + write16(0xED0F); + ModRM(3, to, from); +} + +void PADDSDRtoR(int to, int from) { + write16(0xEE0F); + ModRM(3, to, from); +} + +void PSUBSBRtoR(int to, int from) { + write16(0xE80F); + ModRM(3, to, from); +} + +void PSUBSWRtoR(int to, int from) { + write16(0xE90F); + ModRM(3, to, from); +} + +void PSUBSDRtoR(int to, int from) { + write16(0xEA0F); + ModRM(3, to, from); +} + +void PSUBBRtoR(int to, int from) { + write16(0xF80F); + ModRM(3, to, from); +} + +void PSUBWRtoR(int to, int from) { + write16(0xF90F); + ModRM(3, to, from); +} + +void PSUBDRtoR(int to, int from) { + write16(0xFA0F); + ModRM(3, to, from); +} + +//changed:basara +//P.s.It's sux.Don't use it offten. +void MOVQ64ItoR(int reg,u64 i) +{ + MOVQMtoR(reg,(u32)(x86Ptr)+2+7); + JMP8(8); + write64(i); +} + +void PSUBUSBRtoR(int to, int from) { + write16(0xD80F); + ModRM(3, to, from); +} + +void PSUBUSWRtoR(int to, int from) { + write16(0xD90F); + ModRM(3, to, from); +} + +void PMAXSWRtoR(int to,int from) +{ + write16(0xEE0F); + ModRM(3, to, from); +} + +void PMINSWRtoR(int to,int from) +{ + write16(0xEA0F); + ModRM(3, to, from); +} + +void PCMPEQBRtoR(int to,int from) +{ + write16(0x740F); + ModRM(3, to, from); +} + +void PCMPEQWRtoR(int to,int from) +{ + write16(0x750F); + ModRM(3, to, from); +} + +void PCMPEQDRtoR(int to,int from) +{ + write16(0x760F); + ModRM(3, to, from); +} + +void PCMPGTBRtoR(int to,int from) +{ + write16(0x640F); + ModRM(3, to, from); +} + +void PCMPGTWRtoR(int to,int from) +{ + write16(0x650F); + ModRM(3, to, from); +} + +void PCMPGTDRtoR(int to,int from) +{ + write16(0x660F); + ModRM(3, to, from); +} + +//Basara:Added 10.01.2003 +void PSRLWItoR(int to,int from) +{ + write16(0x710f); + ModRM(2, 2 , to); + write8(from); +} +void PSRLDItoR(int to,int from) +{ + write16(0x720f); + ModRM(2, 2 , to); + write8(from); +} + +void PSLLWItoR(int to,int from) +{ + write16(0x710f); + ModRM(3, 6 , to); + write8(from); +} + +void PSLLDItoR(int to,int from) +{ + write16(0x720f); + ModRM(3, 6 , to); + write8(from); +} + +void PSRAWItoR(int to,int from) +{ + write16(0x710f); + ModRM(3, 4 , to); + write8(from); +} + +void PSRADItoR(int to,int from) +{ + write16(0x720f); + ModRM(3, 4 , to); + write8(from); +} + +/* por m64 to r64 */ +void PORMtoR(int to, u32 from) { + write16(0xEB0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* pxor m64 to r64 */ +void PXORMtoR(int to, u32 from) { + write16(0xEF0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* pand m64 to r64 */ +void PANDMtoR(int to, u32 from) { + write16(0xDB0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* pandn m64 to r64 */ +void PANDNMtoR(int to, u32 from) { + write16(0xDF0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* movd m32 to r64 */ +void MOVDMtoR(int to, u32 from) { + write16(0x6E0F); + ModRM(0, to, DISP32); + write32(from); +} + +/* movq r64 to m32 */ +void MOVDRtoM(u32 to, int from) { + write16(0x7E0F); + ModRM(0, from, DISP32); + write32(to); +} + +/* movd r32 to r64 */ +void MOVD32RtoR(int to, int from) { + write16(0x6E0F); + ModRM(3, to,from); +} + +/* movq r64 to r32 */ +void MOVD64RtoR(int to, int from) { + write16(0x7E0F); + ModRM(3, from,to); +} + +void MOVQRtoR(int to, int from) { + write16(0x6F0F); + ModRM(3, to,from); +} + +void PUNPCKHDQRtoR(int to, int from) { + write16(0x6A0F); + ModRM(3, to,from); +} + +void PUNPCKLDQRtoR(int to, int from) { + write16(0x620F); + ModRM(3, to,from); +} + +////////////////////////////////////////////////////////////////////////// +// SSE intructions +////////////////////////////////////////////////////////////////////////// + +void MOVAPSMtoR(int to, int from) { + write16(0x280f); + ModRM(0, to, DISP32); + write32(from); +} + +void MOVAPSRtoM(int to, int from) { + write16(0x2b0f); + ModRM(0, from, DISP32); + write32(to); +} + +void MOVAPSRtoR(int to, int from) { + write16(0x290f); + ModRM(3, to,from); +} + +void ORPSMtoR(int to, int from) { + write16(0x560f); + ModRM(0, to, DISP32); + write32(from); +} + +void ORPSRtoR(int to, int from) { + write16(0x560f); + ModRM(3, to,from); +} + +void XORPSMtoR(int to, int from) { + write16(0x570f); + ModRM(0, to, DISP32); + write32(from); +} + +void XORPSRtoR(int to, int from) { + write16(0x570f); + ModRM(3, to,from); +} + +void ANDPSMtoR(int to, int from) { + write16(0x540f); + ModRM(0, to, DISP32); + write32(from); +} + +void ANDPSRtoR(int to, int from) { + write16(0x540f); + ModRM(3, to,from); +} + +/* + 3DNOW intructions +*/ + +void PFCMPEQMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0xb0); +} + +void PFCMPGTMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0xa0); +} + +void PFCMPGEMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x90); +} + +void PFADDMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x9e); +} + +void PFADDRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to, from); + write8(0x9e); +} + +void PFSUBMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x9a); +} + +void PFSUBRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to, from); + write8(0x9a); +} + +void PFMULMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0xb4); +} + +void PFMULRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to,from); + write8(0xb4); +} + +void PFRCPMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x96); +} + +void PFRCPRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to,from); + write8(0x96); +} + +void PFRCPIT1RtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to,from); + write8(0xa6); +} + +void PFRCPIT2RtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to,from); + write8(0xb6); +} + +void PFRSQRTRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to,from); + write8(0x97); +} + +void PFRSQIT1RtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to,from); + write8(0xa7); +} + +void PF2IDMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x1d); +} + +void PF2IDRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to, from); + write8(0x1d); +} + +void PI2FDMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x0d); +} + +void PI2FDRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to, from); + write8(0x0d); +} + +/* + 3DNOW Extension intructions +*/ + +void PFMAXMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0xa4); +} + +void PFMAXRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to, from); + write8(0xa4); +} + +void PFMINMtoR(int to, int from) { + write16(0x0f0f); + ModRM(0, to, DISP32); + write32(from); + write8(0x94); +} + +void PFMINRtoR(int to, int from) { + write16(0x0f0f); + ModRM(3, to, from); + write8(0x94); +} + +#endif diff --git a/libpcsxcore/ix86_64/iR3000A-64.c b/libpcsxcore/ix86_64/iR3000A-64.c index 26188c0c..0dccf8bf 100644..100755 --- a/libpcsxcore/ix86_64/iR3000A-64.c +++ b/libpcsxcore/ix86_64/iR3000A-64.c @@ -1,3025 +1,3025 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* i386 assembly functions for R3000A core.
-*/
-
-#ifdef __x86_64__
-
-#include "ix86-64.h"
-#include "../r3000a.h"
-#include "../psxhle.h"
-
-#include <sys/mman.h>
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-uptr* psxRecLUT;
-
-#define PTRMULT (sizeof(uptr) / sizeof(u32))
-
-#undef PC_REC
-#undef PC_REC8
-#undef PC_REC16
-#undef PC_REC32
-#define PC_REC(x) (psxRecLUT[(x) >> 16] + PTRMULT * ((x) & 0xffff))
-#define PC_RECP(x) (*(uptr *)PC_REC(x))
-
-#define RECMEM_SIZE (PTRMULT * 8 * 1024 * 1024)
-
-static char *recMem; /* the recompiled blocks will be here */
-static char *recRAM; /* and the ptr to the blocks here */
-static char *recROM; /* and here */
-
-static u32 pc; /* recompiler pc */
-static u32 pcold; /* recompiler oldpc */
-static int count; /* recompiler intruction count */
-static int branch; /* set for branch */
-static u32 target; /* branch target */
-static u32 resp;
-
-typedef struct {
- int state;
- u32 k;
- int reg;
-} iRegisters;
-
-static iRegisters iRegs[32];
-static iRegisters iRegsS[32];
-
-#define ST_UNK 0
-#define ST_CONST 1
-#define ST_MAPPED 2
-
-#define IsConst(reg) (iRegs[reg].state == ST_CONST)
-#define IsMapped(reg) (iRegs[reg].state == ST_MAPPED)
-
-static void (*recBSC[64])();
-static void (*recSPC[64])();
-static void (*recREG[32])();
-static void (*recCP0[32])();
-static void (*recCP2[64])();
-static void (*recCP2BSC[32])();
-
-#define STACKSIZE 0x18
-static void StackRes()
-{
-#ifdef __x86_64__
- ADD64ItoR(RSP, STACKSIZE);
-#else
- if (resp) ADD32ItoR(ESP, resp);
-#endif
-}
-
-static void MapConst(int reg, u32 _const) {
- iRegs[reg].k = _const;
- iRegs[reg].state = ST_CONST;
-}
-
-static void iFlushReg(int reg) {
- if (IsConst(reg)) {
- MOV32ItoM((uptr)&psxRegs.GPR.r[reg], iRegs[reg].k);
- }
- iRegs[reg].state = ST_UNK;
-}
-
-static void iFlushRegs() {
- int i;
-
- for (i=1; i<32; i++) {
- iFlushReg(i);
- }
-}
-
-static void iRet() {
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((uptr)&psxRegs.cycle, count);
- StackRes();
- RET();
-}
-
-static int iLoadTest() {
- u32 tmp;
-
- // check for load delay
- tmp = psxRegs.code >> 26;
- switch (tmp) {
- case 0x10: // COP0
- switch (_Rs_) {
- case 0x00: // MFC0
- case 0x02: // CFC0
- return 1;
- }
- break;
- case 0x12: // COP2
- switch (_Funct_) {
- case 0x00:
- switch (_Rs_) {
- case 0x00: // MFC2
- case 0x02: // CFC2
- return 1;
- }
- break;
- }
- break;
- case 0x32: // LWC2
- return 1;
- default:
- if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
- return 1;
- }
- break;
- }
- return 0;
-}
-
-/* set a pending branch */
-static void SetBranch() {
- branch = 1;
- psxRegs.code = PSXMu32(pc);
- pc+=4;
-
- if (iLoadTest() == 1) {
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((uptr)&psxRegs.cycle, count);
-
- //PUSH64M((uptr)&target);
- MOV32MtoR(X86ARG2, (uptr)&target);
- //PUSHI(_Rt_);
- MOV64ItoR(X86ARG1, _Rt_);
- CALLFunc((uptr)psxDelayTest);
- StackRes();
- RET();
- return;
- }
-
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs();
- MOV32MtoR(EAX, (uptr)&target);
- MOV32RtoM((uptr)&psxRegs.pc, EAX);
- CALLFunc((uptr)psxBranchTest);
-
- iRet();
-}
-
-static void iJump(u32 branchPC) {
- branch = 1;
- psxRegs.code = PSXMu32(pc);
- pc+=4;
-
- if (iLoadTest() == 1) {
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((uptr)&psxRegs.cycle, count);
-
- //PUSHI(branchPC);
- MOV64ItoR(X86ARG2, branchPC);
- //PUSHI(_Rt_);
- MOV64ItoR(X86ARG1, _Rt_);
- CALLFunc((uptr)psxDelayTest);
- //ADD32ItoR(ESP, 2*8);
- StackRes();
- RET();
- return;
- }
-
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.pc, branchPC);
- CALLFunc((uptr)psxBranchTest);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((uptr)&psxRegs.cycle, count);
- StackRes();
-
- RET();
- //* XXX?
- // maybe just happened an interruption, check so
- CMP32ItoM((uptr)&psxRegs.pc, branchPC);
- j8Ptr[0] = JE8(0);
-
- RET();
-
- x86SetJ8(j8Ptr[0]);
- MOV64MtoR(RAX, PC_REC(branchPC));
- TEST64RtoR(RAX,RAX);
- j8Ptr[1] = JNE8(0);
-
- RET();
-
- x86SetJ8(j8Ptr[1]);
-
- RET();
- //JMP32R(EAX);
- JMPR(EAX);
- //*/
-}
-
-static void iBranch(u32 branchPC, int savectx) {
- u32 respold=0;
-
- if (savectx) {
- respold = resp;
- memcpy(iRegsS, iRegs, sizeof(iRegs));
- }
-
- branch = 1;
- psxRegs.code = PSXMu32(pc);
-
- // the delay test is only made when the branch is taken
- // savectx == 0 will mean that :)
- if (savectx == 0 && iLoadTest() == 1) {
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
- /* store cycle */
- count = (((pc+4) - pcold) / 4) * BIAS;
- ADD32ItoM((uptr)&psxRegs.cycle, count);
- //if (resp) ADD32ItoR(ESP, resp);
-
- //PUSHI(branchPC);
- MOV64ItoR(X86ARG2, branchPC);
- //PUSHI(_Rt_);
- MOV64ItoR(X86ARG1,_Rt_);
- CALLFunc((uptr)psxDelayTest);
- StackRes();
- RET();
- return;
- }
-
- pc+= 4;
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.pc, branchPC);
- CALLFunc((uptr)psxBranchTest);
- /* store cycle */
- count = ((pc - pcold) / 4) * BIAS;
- ADD32ItoM((uptr)&psxRegs.cycle, count);
-
- StackRes();
-
- // maybe just happened an interruption, check so
- CMP32ItoM((uptr)&psxRegs.pc, branchPC);
- j8Ptr[1] = JE8(0);
-
- RET();
-
- x86SetJ8(j8Ptr[1]);
- MOV64MtoR(RAX, PC_REC(branchPC));
- TEST64RtoR(RAX, RAX);
- j8Ptr[2] = JNE8(0);
-
- RET();
-
- x86SetJ8(j8Ptr[2]);
- //JMP32R(EAX);
- JMPR(EAX);
-
- pc-= 4;
- if (savectx) {
- resp = respold;
- memcpy(iRegs, iRegsS, sizeof(iRegs));
- }
-}
-
-
-char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n";
-char *txt1 = "EAX = %x\n";
-char *txt2 = "M32 = %x\n";
-
-/*
-void iLogX86() {
- PUSHA32();
-
- PUSH32R (EDX);
- PUSH32R (ECX);
- PUSH32R (EAX);
- PUSH32M ((uptr)&txt0);
- CALLFunc((uptr)SysPrintf);
- ADD32ItoR(ESP, 4*4);
-
- POPA32();
-}
-*/
-
-void iLogEAX() {
- PUSH64R (EAX);
- PUSH64M ((uptr)&txt1);
- CALLFunc((uptr)SysPrintf);
- ADD32ItoR(ESP, 8*2);
-}
-
-void iLogM32(u32 mem) {
- PUSH64M (mem);
- PUSH64M ((uptr)&txt2);
- CALLFunc((uptr)SysPrintf);
- ADD32ItoR(ESP, 8*2);
-}
-
-#if 0
-static void iDumpRegs() {
- int i, j;
-
- printf("%x %x\n", psxRegs.pc, psxRegs.cycle);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 8; j++)
- printf("%x ", psxRegs.GPR.r[j*i]);
- printf("\n");
- }
-}
-#endif
-
-void iDumpBlock(char *ptr) {
- FILE *f;
- u32 i;
-
- SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle);
-
- for (i = psxRegs.pc; i < pc; i+=4)
- SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
-
- fflush(stdout);
- f = fopen("dump1", "w");
- fwrite(ptr, 1, (uptr)x86Ptr - (uptr)ptr, f);
- fclose(f);
- //system("ndisasm -b64 dump1");
- fflush(stdout);
-}
-
-#define REC_FUNC(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(); \
- MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
- MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
- CALLFunc((uptr)psx##f); \
-/* branch = 2; */\
-}
-
-#define REC_SYS(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(); \
- MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
- MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
- CALLFunc((uptr)psx##f); \
- branch = 2; \
- iRet(); \
-}
-
-#define REC_BRANCH(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(); \
- MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
- MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
- CALLFunc((uptr)psx##f); \
- branch = 2; \
- iRet(); \
-}
-
-static void recRecompile();
-
-static int recInit() {
- int i;
-
- psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
-
- recMem = mmap(0,
- RECMEM_SIZE + PTRMULT*0x1000,
- PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- recRAM = mmap(0,
- 0x280000*PTRMULT,
- PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- recROM = &recRAM[0x200000*PTRMULT];
-
- if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) {
- SysMessage("Error allocating memory"); return -1;
- }
- memset(recMem, 0, RECMEM_SIZE);
- memset(recRAM, 0, 0x200000 * PTRMULT);
- memset(recROM, 0, 0x080000 * PTRMULT);
-
- for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (uptr)&recRAM[PTRMULT*((i & 0x1f) << 16)];
- memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * sizeof(uptr));
- memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * sizeof(uptr));
-
- for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (uptr)&recROM[PTRMULT*(i << 16)];
-
- return 0;
-}
-
-static void recReset() {
- memset(recRAM, 0, 0x200000 * PTRMULT);
- memset(recROM, 0, 0x080000 * PTRMULT);
-
- //x86Init();
- cpudetectInit();
- x86SetPtr(recMem);
-
- branch = 0;
- memset(iRegs, 0, sizeof(iRegs));
- iRegs[0].state = ST_CONST;
- iRegs[0].k = 0;
-}
-
-static void recShutdown() {
- if (recMem == NULL) return;
- free(psxRecLUT);
- munmap(recMem, RECMEM_SIZE + PTRMULT*0x1000);
- munmap(recRAM, 0x280000*PTRMULT);
- x86Shutdown();
-}
-
-static void recError() {
- SysReset();
- ClosePlugins();
- SysMessage("Unrecoverable error while running recompiler\n");
- SysRunGui();
-}
-
-/*__inline*/ static void execute() {
- void (*recFunc)();
- uptr *p;
-
- p = (uptr *)PC_REC(psxRegs.pc);
- // if (!p) { recError(); return; }
-
- if (*p == 0) {
- recRecompile();
- }
-
- if (*p < (uptr)recMem || *p >= (uptr)recMem + RECMEM_SIZE)
- {
- recError();
- return;
- }
- recFunc = (void (*)())*p;
- (*recFunc)();
-}
-
-static void recExecute() {
- for (;;) execute();
-}
-
-static void recExecuteBlock() {
- execute();
-}
-
-static void recClear(u32 Addr, u32 Size) {
- memset((void *)PC_REC(Addr), 0, Size * sizeof(uptr));
-}
-
-static void recNULL() {
-// SysMessage("recUNK: %8.8x\n", psxRegs.code);
-}
-
-/*********************************************************
-* goes to opcodes tables... *
-* Format: table[something....] *
-*********************************************************/
-
-//REC_SYS(SPECIAL);
-#if 1
-static void recSPECIAL() {
- recSPC[_Funct_]();
-}
-#endif
-
-static void recREGIMM() {
- recREG[_Rt_]();
-}
-
-static void recCOP0() {
- recCP0[_Rs_]();
-}
-
-//REC_SYS(COP2);
-#if 1
-static void recCOP2() {
- MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status);
- AND32ItoR(EAX, 0x40000000);
- j32Ptr[31] = JZ32(0);
-
- recCP2[_Funct_]();
-
- x86SetJ32(j32Ptr[31]);
-}
-#endif
-
-static void recBASIC() {
- recCP2BSC[_Rs_]();
-}
-
-//end of Tables opcodes...
-
-/*********************************************************
-* Arithmetic with immediate operand *
-* Format: OP rt, rs, immediate *
-*********************************************************/
-
-#if 0
-REC_FUNC(ADDI);
-REC_FUNC(ADDIU);
-REC_FUNC(ANDI);
-REC_FUNC(ORI);
-REC_FUNC(XORI);
-REC_FUNC(SLTI);
-REC_FUNC(SLTIU);
-#endif
-
-#if 1
-static void recADDIU() {
-// Rt = Rs + Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k+= _Imm_;
- } else {
- if (_Imm_ == 1) {
- INC32M((uptr)&psxRegs.GPR.r[_Rt_]);
- } else if (_Imm_ == -1) {
- DEC32M((uptr)&psxRegs.GPR.r[_Rt_]);
- } else if (_Imm_) {
- ADD32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _Imm_);
- }
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_ == 1) {
- INC32R(EAX);
- } else if (_Imm_ == -1) {
- DEC32R(EAX);
- } else if (_Imm_) {
- ADD32ItoR(EAX, _Imm_);
- }
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-
-static void recADDI() {
-// Rt = Rs + Im
- recADDIU();
-}
-
-static void recSLTI() {
-// Rt = Rs < Im (signed)
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, _Imm_);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-}
-
-static void recSLTIU() {
-// Rt = Rs < Im (unsigned)
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, _Imm_);
- SETB8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-}
-
-static void recANDI() {
-// Rt = Rs And Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k&= _ImmU_;
- } else {
- AND32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- AND32ItoR(EAX, _ImmU_);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-
-static void recORI() {
-// Rt = Rs Or Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k|= _ImmU_;
- } else {
- OR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_ImmU_) OR32ItoR (EAX, _ImmU_);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-
-static void recXORI() {
-// Rt = Rs Xor Im
- if (!_Rt_) return;
-
-// iFlushRegs();
-
- if (_Rs_ == _Rt_) {
- if (IsConst(_Rt_)) {
- iRegs[_Rt_].k^= _ImmU_;
- } else {
- XOR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
- }
- } else {
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
- } else {
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- XOR32ItoR(EAX, _ImmU_);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
- }
-}
-#endif
-//end of * Arithmetic with immediate operand
-
-/*********************************************************
-* Load higher 16 bits of the first word in GPR with imm *
-* Format: OP rt, immediate *
-*********************************************************/
-//REC_FUNC(LUI);
-#if 1
-static void recLUI() {
-// Rt = Imm << 16
- if (!_Rt_) return;
-
- MapConst(_Rt_, psxRegs.code << 16);
-}
-#endif
-//End of Load Higher .....
-
-
-/*********************************************************
-* Register arithmetic *
-* Format: OP rd, rs, rt *
-*********************************************************/
-
-
-#if 0
-REC_FUNC(ADD);
-REC_FUNC(ADDU);
-REC_FUNC(SUB);
-REC_FUNC(SUBU);
-REC_FUNC(AND);
-REC_FUNC(OR);
-REC_FUNC(XOR);
-REC_FUNC(NOR);
-REC_FUNC(SLT);
-REC_FUNC(SLTU);
-#endif
-
-#if 1
-static void recADDU() {
-// Rd = Rs + Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rt_ == _Rd_) {
- if (iRegs[_Rs_].k == 1) {
- INC32M((uptr)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rs_].k == -1) {
- DEC32M((uptr)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rs_].k) {
- ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
- }
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- if (iRegs[_Rs_].k == 1) {
- INC32R(EAX);
- } else if (iRegs[_Rs_].k == 0xffffffff) {
- DEC32R(EAX);
- } else if (iRegs[_Rs_].k) {
- ADD32ItoR(EAX, iRegs[_Rs_].k);
- }
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rs_ == _Rd_) {
- if (iRegs[_Rt_].k == 1) {
- INC32M((uptr)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rt_].k == -1) {
- DEC32M((uptr)&psxRegs.GPR.r[_Rd_]);
- } else if (iRegs[_Rt_].k) {
- ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
- }
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (iRegs[_Rt_].k == 1) {
- INC32R(EAX);
- } else if (iRegs[_Rt_].k == 0xffffffff) {
- DEC32R(EAX);
- } else if (iRegs[_Rt_].k) {
- ADD32ItoR(EAX, iRegs[_Rt_].k);
- }
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rs_ == _Rd_) { // Rd+= Rt
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (_Rt_ == _Rd_) { // Rd+= Rs
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else { // Rd = Rs + Rt
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
- }
-}
-
-static void recADD() {
-// Rd = Rs + Rt
- recADDU();
-}
-
-static void recSUBU() {
-// Rd = Rs - Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SUB32ItoR(EAX, iRegs[_Rt_].k);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSUB() {
-// Rd = Rs - Rt
- recSUBU();
-}
-
-static void recAND() {
-// Rd = Rs And Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rd_ == _Rt_) { // Rd&= Rs
- AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
- } else {
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rd_ == _Rs_) { // Rd&= kRt
- AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
- } else { // Rd = Rs & kRt
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- AND32ItoR(EAX, iRegs[_Rt_].k);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- if (_Rs_ == _Rd_) { // Rd&= Rt
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (_Rt_ == _Rd_) { // Rd&= Rs
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else { // Rd = Rs & Rt
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
- }
-}
-
-static void recOR() {
-// Rd = Rs Or Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- OR32ItoR (EAX, iRegs[_Rt_].k);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recXOR() {
-// Rd = Rs Xor Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- XOR32ItoR(EAX, iRegs[_Rt_].k);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recNOR() {
-// Rd = Rs Nor Rt
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k));
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- NOT32R (EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- OR32ItoR (EAX, iRegs[_Rt_].k);
- NOT32R (EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- NOT32R (EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSLT() {
-// Rd = Rs < Rt (signed)
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, iRegs[_Rt_].k);
- SETL8R (EAX);
- AND32ItoR(EAX, 0xff);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- 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);
- }
-}
-
-static void recSLTU() {
-// Rd = Rs < Rt (unsigned)
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rs_].k);
- CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- SBB32RtoR(EAX, EAX);
- NEG32R (EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- CMP32ItoR(EAX, iRegs[_Rt_].k);
- SBB32RtoR(EAX, EAX);
- NEG32R (EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- 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);
- }
-}
-#endif
-//End of * Register arithmetic
-
-/*********************************************************
-* Register mult/div & Register trap logic *
-* Format: OP rs, rt *
-*********************************************************/
-
-#if 0
-REC_FUNC(MULT);
-REC_FUNC(MULTU);
-REC_FUNC(DIV);
-REC_FUNC(DIVU);
-#endif
-
-#if 1
-static void recMULT() {
-// Lo/Hi = Rs * Rt (signed)
-
-// iFlushRegs();
-
- if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
- (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
- XOR32RtoR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- return;
- }
-
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- }
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k);
- IMUL32R (EDX);
- } else {
- IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]);
- }
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
-}
-
-static void recMULTU() {
-// Lo/Hi = Rs * Rt (unsigned)
-
-// iFlushRegs();
-
- if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
- (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
- XOR32RtoR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- return;
- }
-
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- }
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k);
- MUL32R (EDX);
- } else {
- MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]);
- }
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
-}
-
-static void recDIV() {
-// Lo/Hi = Rs / Rt (signed)
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- if (iRegs[_Rt_].k == 0) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- }
- return;
- }
- MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
- CMP32ItoR(ECX, 0);
- j8Ptr[0] = JE8(0);
- }
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- }
- CDQ();
- IDIV32R (ECX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
- if (!IsConst(_Rt_)) {
- j8Ptr[1] = JMP8(1);
-
- x86SetJ8(j8Ptr[0]);
-
- MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- }
-
- x86SetJ8(j8Ptr[1]);
- }
-}
-
-static void recDIVU() {
-// Lo/Hi = Rs / Rt (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- if (iRegs[_Rt_].k == 0) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- }
- return;
- }
- MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
- CMP32ItoR(ECX, 0);
- j8Ptr[0] = JE8(0);
- }
- if (IsConst(_Rs_)) {
- MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- }
- XOR32RtoR(EDX, EDX);
- DIV32R (ECX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
- if (!IsConst(_Rt_)) {
- j8Ptr[1] = JMP8(1);
-
- x86SetJ8(j8Ptr[0]);
-
- MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff);
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- }
-
- x86SetJ8(j8Ptr[1]);
- }
-}
-#endif
-//End of * Register mult/div & Register trap logic
-
-#if 0
-REC_FUNC(LB);
-REC_FUNC(LBU);
-REC_FUNC(LH);
-REC_FUNC(LHU);
-REC_FUNC(LW);
-
-REC_FUNC(SB);
-REC_FUNC(SH);
-REC_FUNC(SW);
-
-REC_FUNC(LWL);
-REC_FUNC(LWR);
-REC_FUNC(SWL);
-REC_FUNC(SWR);
-#endif
-
-
-static void SetArg_OfB(x86IntRegType arg) {
- if (IsConst(_Rs_))
-#ifdef __x86_64__
- MOV64ItoR(arg, iRegs[_Rs_].k + _Imm_);
-#else
- PUSH32I (iRegs[_Rs_].k + _Imm_);
-#endif
- else {
-#ifdef __x86_64__
- MOV32MtoR(arg, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_)
- ADD32ItoR(arg, _Imm_);
-#else
- if (_Imm_) {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- ADD32ItoR(EAX, _Imm_);
- PUSH32R (EAX);
- } else {
- PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]);
- }
-#endif
- }
-#ifndef __x86_64__
- resp += 4;
-#endif
-}
-
-#if 1
-static void recLB() {
-// Rt = mem[Rs + Im] (signed)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRs8(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
-// SysPrintf("unhandled r8 %x\n", addr);
- }
-
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemRead8);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVSX32R8toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
-}
-
-static void recLBU() {
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu8(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
-// SysPrintf("unhandled r8u %x\n", addr);
- }
-
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemRead8);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVZX32R8toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
-}
-
-static void recLH() {
-// Rt = mem[Rs + Im] (signed)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRs16(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVSX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
-// SysPrintf("unhandled r16 %x\n", addr);
- }
-
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemRead16);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVSX32R16toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
-}
-
-static void recLHU() {
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu16(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOVZX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80) {
- if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- //PUSHI (addr);
- MOV64ItoR(X86ARG1, addr);
- //CALLFunc ((uptr)SPU_readRegister);
- MOV64ItoR(RAX, (uptr)SPU_readRegister);
- CALL64R(RAX);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
-#ifndef __WIN32__
- resp+= 4;
-#endif
- return;
- }
- switch (addr) {
- case 0x1f801100: case 0x1f801110: case 0x1f801120:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- //PUSHI((addr >> 4) & 0x3);
- MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
- CALLFunc((uptr)psxRcntRcount);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- resp+= 4;
- return;
-
- case 0x1f801104: case 0x1f801114: case 0x1f801124:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
- CALLFunc((uptr)psxRcntRmode);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- resp+= 4;
- return;
-
- case 0x1f801108: case 0x1f801118: case 0x1f801128:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
- CALLFunc((uptr)psxRcntRtarget);
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- resp+= 4;
- return;
- }
- }
-// SysPrintf("unhandled r16u %x\n", addr);
- }
-
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemRead16);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOVZX32R16toR(EAX, EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
-}
-
-static void recLW() {
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu32(addr));
- return;
- }
- if ((t & 0x1fe0) == 0) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80) {
- switch (addr) {
- case 0x1f801080: case 0x1f801084: case 0x1f801088:
- case 0x1f801090: case 0x1f801094: case 0x1f801098:
- case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8:
- case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8:
- case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8:
- case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8:
- case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8:
- case 0x1f801070: case 0x1f801074:
- case 0x1f8010f0: case 0x1f8010f4:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
-
- case 0x1f801810:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- CALLFunc((uptr)GPU_readData);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
-
- case 0x1f801814:
- if (!_Rt_) return;
- iRegs[_Rt_].state = ST_UNK;
-
- CALLFunc((uptr)GPU_readStatus);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-// SysPrintf("unhandled r32 %x\n", addr);
- }
-
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemRead32);
- if (_Rt_) {
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- }
-// ADD32ItoR(ESP, 4);
-}
-
-extern u32 LWL_MASK[4];
-extern u32 LWL_SHIFT[4];
-
-void iLWLk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- AND32ItoR(ECX, LWL_MASK[shift]);
- SHL32ItoR(EAX, LWL_SHIFT[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recLWL() {
-// Rt = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0) {
- MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
- iLWLk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
- iLWLk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- //PUSH64R (EAX);
- AND32ItoR(EAX, ~3);
- //PUSH64R (EAX);
- MOV32RtoR(X86ARG1, EAX);
- CALLFunc((uptr)psxMemRead32);
-
- if (_Rt_) {
- //ADD32ItoR(ESP, 4);
- //POP64R (EDX);
- if (IsConst(_Rs_)) MOV32ItoR(EDX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EDX, _Imm_);
- }
-
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV64ItoR(ECX, (uptr)LWL_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
-
- MOV64ItoR(ECX, (uptr)LWL_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
-
- OR32RtoR(EAX, EDX);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- //} else {
- //ADD64ItoR(RSP, 8);
- //resp+= 8;
- }
-}
-
-/*
-static void recLWBlock(int count) {
- u32 *code = PSXM(pc);
- int i, respsave;
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- // since bios is readonly it won't change
- for (i=0; i<count; i++, code++, addr+=4) {
- if (_fRt_(*code)) {
- MapConst(_fRt_(*code), psxRu32(addr));
- }
- }
- return;
- }
- if ((t & 0x1fe0) == 0) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (!_fRt_(*code)) return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (!_fRt_(*code)) return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- }
-
- SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemPointer);
-// ADD32ItoR(ESP, 4);
-
- respsave = resp; resp = 0;
- TEST64RtoR(RAX,RAX);
- j32Ptr[4] = JZ32(0);
- XOR32RtoR(ECX, ECX);
- for (i=0; i<count; i++, code++) {
- if (_fRt_(*code)) {
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV64RmStoR(EDX, EAX, ECX, 2);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EDX);
- }
- if (i != (count-1)) INC32R(ECX);
- }
- j32Ptr[5] = JMP32(0);
- x86SetJ32(j32Ptr[4]);
- for (i=0, code = PSXM(pc); i<count; i++, code++) {
- psxRegs.code = *code;
- recLW();
- }
-#ifndef __x86_64__
- ADD32ItoR(ESP, resp);
-#endif
- x86SetJ32(j32Ptr[5]);
- resp = respsave;
-}
-*/
-
-extern u32 LWR_MASK[4];
-extern u32 LWR_SHIFT[4];
-
-void iLWRk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- AND32ItoR(ECX, LWR_MASK[shift]);
- SHR32ItoR(EAX, LWR_SHIFT[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recLWR() {
-// Rt = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0) {
- MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
- iLWRk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
- iLWRk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSHR(EAX);
- AND32ItoR(EAX, ~3);
- MOV32RtoR(X86ARG1, EAX);
- CALLFunc((uptr)psxMemRead32);
-
- POPR (EDX);
- if (_Rt_) {
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV64ItoR(ECX, (uptr)LWR_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
-
- MOV64ItoR(ECX, (uptr)LWR_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
-
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
-
- OR32RtoR(EAX, EDX);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
- //} else {
- //resp+= 8;
- }
-}
-
-static void recSB() {
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV8ItoM((uptr)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
- } else {
- MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV8RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
- }
- MOV32ItoR(X86ARG2, 1);
- MOV32ItoR(X86ARG1, addr & ~3);
- CALLFunc((uptr)&recClear);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV8ItoM((uptr)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
- } else {
- MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV8RtoM((uptr)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
-// SysPrintf("unhandled w8 %x\n", addr);
- }
-
- if (IsConst(_Rt_)) {
- MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemWrite8);
-// ADD32ItoR(ESP, 8);
-}
-
-static void recSH() {
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV16ItoM((uptr)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
- } else {
- MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV16RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
- }
- MOV32ItoR(X86ARG2, 1);
- MOV32ItoR(X86ARG1, addr & ~3);
- CALLFunc((uptr)&recClear);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV16ItoM((uptr)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
- } else {
- MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV16RtoM((uptr)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
- if (t == 0x1f80) {
- if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
- if (IsConst(_Rt_)) {
- MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- MOV64ItoR(X86ARG1, addr);
- CALLFunc ((uptr)SPU_writeRegister);
-#ifndef __WIN32__
- //resp+= 8;
-#endif
- return;
- }
- }
-// SysPrintf("unhandled w16 %x\n", addr);
- }
-
- if (IsConst(_Rt_)) {
- MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemWrite16);
-// ADD32ItoR(ESP, 8);
-}
-
-static void recSW() {
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
- }
- MOV32ItoR(X86ARG2, 1);
- MOV32ItoR(X86ARG1, addr);
- CALLFunc((uptr)&recClear);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV32ItoM((uptr)&psxH[addr & 0xfff], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
- if (t == 0x1f80) {
- switch (addr) {
- case 0x1f801080: case 0x1f801084:
- case 0x1f801090: case 0x1f801094:
- case 0x1f8010a0: case 0x1f8010a4:
- case 0x1f8010b0: case 0x1f8010b4:
- case 0x1f8010c0: case 0x1f8010c4:
- case 0x1f8010d0: case 0x1f8010d4:
- case 0x1f8010e0: case 0x1f8010e4:
- case 0x1f801074:
- case 0x1f8010f0:
- if (IsConst(_Rt_)) {
- MOV32ItoM((uptr)&psxH[addr & 0xffff], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32RtoM((uptr)&psxH[addr & 0xffff], EAX);
- }
- return;
-
- case 0x1f801810:
- if (IsConst(_Rt_)) {
- MOV64ItoR(X86ARG1, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- CALLFunc((uptr)GPU_writeData);
-#ifndef __WIN32__
- //resp+= 4;
-#endif
- return;
-
- case 0x1f801814:
- if (IsConst(_Rt_)) {
- MOV64ItoR(X86ARG1, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- CALLFunc((uptr)GPU_writeStatus);
-#ifndef __WIN32__
- //resp+= 4;
-#endif
- }
- }
-// SysPrintf("unhandled w32 %x\n", addr);
- }
-
- if (IsConst(_Rt_)) {
- MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- //resp+= 8;
-}
-
-/*
-static void recSWBlock(int count) {
- u32 *code;
- int i, respsave;
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
- code = PSXM(pc);
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (IsConst(_fRt_(*code))) {
- MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]);
- MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
- }
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (!_fRt_(*code)) return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- }
-
- SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
- SetArg_OfB(X86ARG1);
- CALLFunc((uptr)psxMemPointer);
-// ADD32ItoR(ESP, 4);
- //resp+= 4;
-
- respsave = resp; resp = 0;
- TEST64RtoR(RAX,RAX);
- j32Ptr[4] = JZ32(0);
- XOR32RtoR(ECX, ECX);
- for (i=0, code = PSXM(pc); i<count; i++, code++) {
- if (IsConst(_fRt_(*code))) {
- MOV32ItoR(EDX, iRegs[_fRt_(*code)].k);
- } else {
- MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]);
- }
- MOV32RtoRmS(EAX, ECX, 2, EDX);
- if (i != (count-1)) INC32R(ECX);
- }
- j32Ptr[5] = JMP32(0);
- x86SetJ32(j32Ptr[4]);
- for (i=0, code = PSXM(pc); i<count; i++, code++) {
- psxRegs.code = *code;
- recSW();
- }
- //ADD32ItoR(ESP, resp);
- x86SetJ32(j32Ptr[5]);
- resp = respsave;
-}
-*/
-
-extern u32 SWL_MASK[4];
-extern u32 SWL_SHIFT[4];
-
-void iSWLk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SHR32ItoR(ECX, SWL_SHIFT[shift]);
- AND32ItoR(EAX, SWL_MASK[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recSWL() {
-// mem[Rs + Im] = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
- iSWLk(addr & 3);
- MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
- iSWLk(addr & 3);
- MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSHR (EAX);
- AND32ItoR(EAX, ~3);
- MOV32RtoR(X86ARG1, EAX);
-
- CALLFunc((uptr)psxMemRead32);
-
- POPR (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV64ItoR(ECX, (uptr)SWL_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
-
- MOV64ItoR(ECX, (uptr)SWL_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
-
- OR32RtoR (EAX, EDX);
- MOV32RtoR(X86ARG2, EAX);
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- AND32ItoR(EAX, ~3);
- MOV32RtoR(X86ARG1, EAX);
-
- CALLFunc((uptr)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- //resp+= 8;
-}
-
-extern u32 SWR_MASK[4];
-extern u32 SWR_SHIFT[4];
-
-void iSWRk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SHL32ItoR(ECX, SWR_SHIFT[shift]);
- AND32ItoR(EAX, SWR_MASK[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recSWR() {
-// mem[Rs + Im] = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
- iSWRk(addr & 3);
- MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
- iSWRk(addr & 3);
- MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSHR (EAX);
-
- AND32ItoR(EAX, ~3);
- MOV32RtoR(X86ARG1, EAX);
-
- CALLFunc((uptr)psxMemRead32);
-
- POPR (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV64ItoR(ECX, (uptr)SWR_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
-
- MOV64ItoR(ECX, (uptr)SWR_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
-
- OR32RtoR (EAX, EDX);
- MOV32RtoR(X86ARG2, EAX);
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- AND32ItoR(EAX, ~3);
- MOV32RtoR(X86ARG1, EAX);
- CALLFunc((uptr)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- //resp+= 8;
-}
-
-#endif
-
-#if 0
-REC_FUNC(SLL);
-REC_FUNC(SRL);
-REC_FUNC(SRA);
-#endif
-#if 1
-static void recSLL() {
-// Rd = Rt << Sa
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- if (_Sa_) SHL32ItoR(EAX, _Sa_);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRL() {
-// Rd = Rt >> Sa
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- if (_Sa_) SHR32ItoR(EAX, _Sa_);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRA() {
-// Rd = Rt >> Sa
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- if (_Sa_) SAR32ItoR(EAX, _Sa_);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-#endif
-
-#if 0
-REC_FUNC(SLLV);
-REC_FUNC(SRLV);
-REC_FUNC(SRAV);
-#endif
-
-#if 1
-static void recSLLV() {
-// Rd = Rt << Rs
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32ItoR(ECX, iRegs[_Rs_].k);
- SHL32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rt_].k);
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SHL32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SHL32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRLV() {
-// Rd = Rt >> Rs
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32ItoR(ECX, iRegs[_Rs_].k);
- SHR32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rt_].k);
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SHR32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SHR32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-
-static void recSRAV() {
-// Rd = Rt >> Rs
- if (!_Rd_) return;
-
-// iFlushRegs();
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k);
- } else if (IsConst(_Rs_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32ItoR(ECX, iRegs[_Rs_].k);
- SAR32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else if (IsConst(_Rt_)) {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32ItoR(EAX, iRegs[_Rt_].k);
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SAR32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- } else {
- iRegs[_Rd_].state = ST_UNK;
-
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
- SAR32CLtoR(EAX);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
- }
-}
-#endif
-
-#if 0
-REC_SYS(SYSCALL);
-REC_SYS(BREAK);
-#endif
-
-int dump = 0;
-
-#if 1
-static void recSYSCALL() {
-// dump=1;
- iFlushRegs();
-
- MOV32ItoR(EAX, pc - 4);
- MOV32RtoM((uptr)&psxRegs.pc, EAX);
- MOV64ItoR(X86ARG2, branch == 1 ? 1 : 0);
- MOV64ItoR(X86ARG1, 0x20);
- CALLFunc((uptr)psxException);
- //ADD32ItoR(ESP, 8);
-
- branch = 2;
- iRet();
-}
-
-static void recBREAK() {
-}
-#endif
-
-#if 0
-REC_FUNC(MFHI);
-REC_FUNC(MTHI);
-REC_FUNC(MFLO);
-REC_FUNC(MTLO);
-#endif
-#if 1
-static void recMFHI() {
-// Rd = Hi
- if (!_Rd_) return;
-
- iRegs[_Rd_].state = ST_UNK;
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
-}
-
-static void recMTHI() {
-// Hi = Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
- }
-}
-
-static void recMFLO() {
-// Rd = Lo
- if (!_Rd_) return;
-
- iRegs[_Rd_].state = ST_UNK;
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
-}
-
-static void recMTLO() {
-// Lo = Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&psxRegs.GPR.n.lo, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
- }
-}
-#endif
-
-#if 0
-REC_BRANCH(J);
-REC_BRANCH(JR);
-REC_BRANCH(JAL);
-REC_BRANCH(JALR);
-REC_BRANCH(BLTZ);
-REC_BRANCH(BGTZ);
-REC_BRANCH(BLTZAL);
-REC_BRANCH(BGEZAL);
-REC_BRANCH(BNE);
-REC_BRANCH(BEQ);
-REC_BRANCH(BLEZ);
-REC_BRANCH(BGEZ);
-#endif
-#if 1
-static void recBLTZ() {
-// Branch if Rs < 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
-
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k < 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JL32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBGTZ() {
-// Branch if Rs > 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k > 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JG32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBLTZAL() {
-// Branch if Rs < 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k < 0) {
- MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JL32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBGEZAL() {
-// Branch if Rs >= 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k >= 0) {
- MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JGE32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recJ() {
-// j target
-
- iJump(_Target_ * 4 + (pc & 0xf0000000));
-}
-
-static void recJAL() {
-// jal target
-
- MapConst(31, pc + 4);
-
- iJump(_Target_ * 4 + (pc & 0xf0000000));
-}
-
-static void recJR() {
-// jr Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&target, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&target, EAX);
- }
-
- SetBranch();
-}
-
-static void recJALR() {
-// jalr Rs
-
- if (IsConst(_Rs_)) {
- MOV32ItoM((uptr)&target, iRegs[_Rs_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- MOV32RtoM((uptr)&target, EAX);
- }
-
- if (_Rd_) {
- MapConst(_Rd_, pc + 4);
- }
-
- SetBranch();
-}
-
-static void recBEQ() {
-// Branch if Rs == Rt
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (_Rs_ == _Rt_) {
- iJump(bpc);
- } else {
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- } else if (IsConst(_Rs_)) {
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
- } else if (IsConst(_Rt_)) {
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
-
- j32Ptr[4] = JE32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
- }
-}
-
-static void recBNE() {
-// Branch if Rs != Rt
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- } else if (IsConst(_Rs_)) {
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
- } else if (IsConst(_Rt_)) {
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
- CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- }
- j32Ptr[4] = JNE32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBLEZ() {
-// Branch if Rs <= 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k <= 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JLE32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBGEZ() {
-// Branch if Rs >= 0
- u32 bpc = _Imm_ * 4 + pc;
-
-// iFlushRegs();
- if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
- return;
- }
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k >= 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
- j32Ptr[4] = JGE32(0);
-
- iBranch(pc+4, 1);
-
- x86SetJ32(j32Ptr[4]);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-#endif
-
-#if 0
-REC_FUNC(MFC0);
-REC_SYS(MTC0);
-REC_FUNC(CFC0);
-REC_SYS(CTC0);
-REC_FUNC(RFE);
-#endif
-//REC_SYS(MTC0);
-#if 1
-static void recMFC0() {
-// Rt = Cop0->Rd
- if (!_Rt_) return;
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]);
- MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
-}
-
-static void recCFC0() {
-// Rt = Cop0->Rd
-
- recMFC0();
-}
-
-//*
-void psxMTC0();
-static void recMTC0() {
-// Cop0->Rd = Rt
-
- if (IsConst(_Rt_)) {
- switch (_Rd_) {
- case 12:
- MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
- break;
- case 13:
- MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
- break;
- default:
- MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
- break;
- }
- } else {
- MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
- switch (_Rd_) {
- case 13:
- AND32ItoR(EAX, ~(0xfc00));
- break;
- }
- MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX);
- }
-
- if (_Rd_ == 12 || _Rd_ == 13) {
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.pc, (u32)pc);
- CALLFunc((uptr)psxTestSWInts);
- if (branch == 0) {
- branch = 2;
- iRet();
- }
- }
-}//*/
-
-static void recCTC0() {
-// Cop0->Rd = Rt
-
- recMTC0();
-}
-
-static void recRFE() {
- 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);
-
- iFlushRegs();
- MOV32ItoM((uptr)&psxRegs.pc, (u32)pc);
- CALLFunc((uptr)psxTestSWInts);
- if (branch == 0) {
- branch = 2;
- iRet();
- }
-}
-#endif
-
-#include "iGte.h"
-
-//
-
-static void recHLE() {
- iFlushRegs();
-
- CALLFunc((uptr)psxHLEt[psxRegs.code & 0xffff]);
- branch = 2;
- iRet();
-}
-
-//
-
-static void (*recBSC[64])() = {
- recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
- recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI ,
- recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
- recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL,
- recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL,
- recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recSPC[64])() = {
- recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV,
- recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
- recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL,
- recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL,
- recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR ,
- recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL
-};
-
-static void (*recREG[32])() = {
- recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recCP0[32])() = {
- recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recCP2[64])() = {
- recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00
- recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08
- recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10
- recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18
- recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20
- recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28
- recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30
- recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38
-};
-
-static void (*recCP2BSC[32])() = {
- recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, 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
-};
-
-
-static void recRecompile() {
- char *p;
- char *ptr;
-
- dump = 0;
- resp = 0;
-
- /* if x86Ptr reached the mem limit reset whole mem */
- if (((uptr)x86Ptr - (uptr)recMem) >= (RECMEM_SIZE - PTRMULT*0x10000))
- recReset();
-
- x86Align(32);
- ptr = x86Ptr;
-
- PC_RECP(psxRegs.pc) = (uptr)x86Ptr;
- pc = psxRegs.pc;
- pcold = pc;
-
- //Make some stack space for function arguments spill (x86-64 calling conventions)
- // 0x38 = 7 args, should be plenty...
- SUB64ItoR(RSP, STACKSIZE);
-
- for (count=0; count<500;) {
- p = (char *)PSXM(pc);
- if (p == NULL) recError();
- psxRegs.code = *(u32 *)p;
-/*
- if ((psxRegs.code >> 26) == 0x23) { // LW
- int i;
- u32 code;
-
- for (i=1;; i++) {
- p = (char *)PSXM(pc+i*4);
- if (p == NULL) recError();
- code = *(u32 *)p;
-
- if ((code >> 26) != 0x23 ||
- _fRs_(code) != _Rs_ ||
- _fImm_(code) != (_Imm_+i*4))
- break;
- }
- if (i > 1) {
- recLWBlock(i);
- pc = pc + i*4; continue;
- }
- }
-
- if ((psxRegs.code >> 26) == 0x2b) { // SW
- int i;
- u32 code;
-
- for (i=1;; i++) {
- p = (char *)PSXM(pc+i*4);
- if (p == NULL) recError();
- code = *(u32 *)p;
-
- if ((code >> 26) != 0x2b ||
- _fRs_(code) != _Rs_ ||
- _fImm_(code) != (_Imm_+i*4))
- break;
- }
- if (i > 1) {
- recSWBlock(i);
- pc = pc + i*4; continue;
- }
- }*/
-
- pc+=4; count++;
- recBSC[psxRegs.code>>26]();
-
- if (branch) {
- branch = 0;
- if (dump) iDumpBlock(ptr);
- return;
- }
- }
-
- iFlushRegs();
-
- MOV32ItoM((uptr)&psxRegs.pc, pc);
- iRet();
-}
-
-
-R3000Acpu psxRec = {
- recInit,
- recReset,
- recExecute,
- recExecuteBlock,
- recClear,
- recShutdown
-};
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* i386 assembly functions for R3000A core. +*/ + +#ifdef __x86_64__ + +#include "ix86-64.h" +#include "../r3000a.h" +#include "../psxhle.h" + +#include <sys/mman.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +uptr* psxRecLUT; + +#define PTRMULT (sizeof(uptr) / sizeof(u32)) + +#undef PC_REC +#undef PC_REC8 +#undef PC_REC16 +#undef PC_REC32 +#define PC_REC(x) (psxRecLUT[(x) >> 16] + PTRMULT * ((x) & 0xffff)) +#define PC_RECP(x) (*(uptr *)PC_REC(x)) + +#define RECMEM_SIZE (PTRMULT * 8 * 1024 * 1024) + +static char *recMem; /* the recompiled blocks will be here */ +static char *recRAM; /* and the ptr to the blocks here */ +static char *recROM; /* and here */ + +static u32 pc; /* recompiler pc */ +static u32 pcold; /* recompiler oldpc */ +static int count; /* recompiler intruction count */ +static int branch; /* set for branch */ +static u32 target; /* branch target */ +static u32 resp; + +typedef struct { + int state; + u32 k; + int reg; +} iRegisters; + +static iRegisters iRegs[32]; +static iRegisters iRegsS[32]; + +#define ST_UNK 0 +#define ST_CONST 1 +#define ST_MAPPED 2 + +#define IsConst(reg) (iRegs[reg].state == ST_CONST) +#define IsMapped(reg) (iRegs[reg].state == ST_MAPPED) + +static void (*recBSC[64])(); +static void (*recSPC[64])(); +static void (*recREG[32])(); +static void (*recCP0[32])(); +static void (*recCP2[64])(); +static void (*recCP2BSC[32])(); + +#define STACKSIZE 0x18 +static void StackRes() +{ +#ifdef __x86_64__ + ADD64ItoR(RSP, STACKSIZE); +#else + if (resp) ADD32ItoR(ESP, resp); +#endif +} + +static void MapConst(int reg, u32 _const) { + iRegs[reg].k = _const; + iRegs[reg].state = ST_CONST; +} + +static void iFlushReg(int reg) { + if (IsConst(reg)) { + MOV32ItoM((uptr)&psxRegs.GPR.r[reg], iRegs[reg].k); + } + iRegs[reg].state = ST_UNK; +} + +static void iFlushRegs() { + int i; + + for (i=1; i<32; i++) { + iFlushReg(i); + } +} + +static void iRet() { + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((uptr)&psxRegs.cycle, count); + StackRes(); + RET(); +} + +static int iLoadTest() { + u32 tmp; + + // check for load delay + tmp = psxRegs.code >> 26; + switch (tmp) { + case 0x10: // COP0 + switch (_Rs_) { + case 0x00: // MFC0 + case 0x02: // CFC0 + return 1; + } + break; + case 0x12: // COP2 + switch (_Funct_) { + case 0x00: + switch (_Rs_) { + case 0x00: // MFC2 + case 0x02: // CFC2 + return 1; + } + break; + } + break; + case 0x32: // LWC2 + return 1; + default: + if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR + return 1; + } + break; + } + return 0; +} + +/* set a pending branch */ +static void SetBranch() { + branch = 1; + psxRegs.code = PSXMu32(pc); + pc+=4; + + if (iLoadTest() == 1) { + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.code, psxRegs.code); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((uptr)&psxRegs.cycle, count); + + //PUSH64M((uptr)&target); + MOV32MtoR(X86ARG2, (uptr)&target); + //PUSHI(_Rt_); + MOV64ItoR(X86ARG1, _Rt_); + CALLFunc((uptr)psxDelayTest); + StackRes(); + RET(); + return; + } + + recBSC[psxRegs.code>>26](); + + iFlushRegs(); + MOV32MtoR(EAX, (uptr)&target); + MOV32RtoM((uptr)&psxRegs.pc, EAX); + CALLFunc((uptr)psxBranchTest); + + iRet(); +} + +static void iJump(u32 branchPC) { + branch = 1; + psxRegs.code = PSXMu32(pc); + pc+=4; + + if (iLoadTest() == 1) { + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.code, psxRegs.code); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((uptr)&psxRegs.cycle, count); + + //PUSHI(branchPC); + MOV64ItoR(X86ARG2, branchPC); + //PUSHI(_Rt_); + MOV64ItoR(X86ARG1, _Rt_); + CALLFunc((uptr)psxDelayTest); + //ADD32ItoR(ESP, 2*8); + StackRes(); + RET(); + return; + } + + recBSC[psxRegs.code>>26](); + + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.pc, branchPC); + CALLFunc((uptr)psxBranchTest); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((uptr)&psxRegs.cycle, count); + StackRes(); + + RET(); + //* XXX? + // maybe just happened an interruption, check so + CMP32ItoM((uptr)&psxRegs.pc, branchPC); + j8Ptr[0] = JE8(0); + + RET(); + + x86SetJ8(j8Ptr[0]); + MOV64MtoR(RAX, PC_REC(branchPC)); + TEST64RtoR(RAX,RAX); + j8Ptr[1] = JNE8(0); + + RET(); + + x86SetJ8(j8Ptr[1]); + + RET(); + //JMP32R(EAX); + JMPR(EAX); + //*/ +} + +static void iBranch(u32 branchPC, int savectx) { + u32 respold=0; + + if (savectx) { + respold = resp; + memcpy(iRegsS, iRegs, sizeof(iRegs)); + } + + branch = 1; + psxRegs.code = PSXMu32(pc); + + // the delay test is only made when the branch is taken + // savectx == 0 will mean that :) + if (savectx == 0 && iLoadTest() == 1) { + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.code, psxRegs.code); + /* store cycle */ + count = (((pc+4) - pcold) / 4) * BIAS; + ADD32ItoM((uptr)&psxRegs.cycle, count); + //if (resp) ADD32ItoR(ESP, resp); + + //PUSHI(branchPC); + MOV64ItoR(X86ARG2, branchPC); + //PUSHI(_Rt_); + MOV64ItoR(X86ARG1,_Rt_); + CALLFunc((uptr)psxDelayTest); + StackRes(); + RET(); + return; + } + + pc+= 4; + recBSC[psxRegs.code>>26](); + + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.pc, branchPC); + CALLFunc((uptr)psxBranchTest); + /* store cycle */ + count = ((pc - pcold) / 4) * BIAS; + ADD32ItoM((uptr)&psxRegs.cycle, count); + + StackRes(); + + // maybe just happened an interruption, check so + CMP32ItoM((uptr)&psxRegs.pc, branchPC); + j8Ptr[1] = JE8(0); + + RET(); + + x86SetJ8(j8Ptr[1]); + MOV64MtoR(RAX, PC_REC(branchPC)); + TEST64RtoR(RAX, RAX); + j8Ptr[2] = JNE8(0); + + RET(); + + x86SetJ8(j8Ptr[2]); + //JMP32R(EAX); + JMPR(EAX); + + pc-= 4; + if (savectx) { + resp = respold; + memcpy(iRegs, iRegsS, sizeof(iRegs)); + } +} + + +char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +char *txt1 = "EAX = %x\n"; +char *txt2 = "M32 = %x\n"; + +/* +void iLogX86() { + PUSHA32(); + + PUSH32R (EDX); + PUSH32R (ECX); + PUSH32R (EAX); + PUSH32M ((uptr)&txt0); + CALLFunc((uptr)SysPrintf); + ADD32ItoR(ESP, 4*4); + + POPA32(); +} +*/ + +void iLogEAX() { + PUSH64R (EAX); + PUSH64M ((uptr)&txt1); + CALLFunc((uptr)SysPrintf); + ADD32ItoR(ESP, 8*2); +} + +void iLogM32(u32 mem) { + PUSH64M (mem); + PUSH64M ((uptr)&txt2); + CALLFunc((uptr)SysPrintf); + ADD32ItoR(ESP, 8*2); +} + +#if 0 +static void iDumpRegs() { + int i, j; + + printf("%x %x\n", psxRegs.pc, psxRegs.cycle); + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) + printf("%x ", psxRegs.GPR.r[j*i]); + printf("\n"); + } +} +#endif + +void iDumpBlock(char *ptr) { + FILE *f; + u32 i; + + SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle); + + for (i = psxRegs.pc; i < pc; i+=4) + SysPrintf("%s\n", disR3000AF(PSXMu32(i), i)); + + fflush(stdout); + f = fopen("dump1", "w"); + fwrite(ptr, 1, (uptr)x86Ptr - (uptr)ptr, f); + fclose(f); + //system("ndisasm -b64 dump1"); + fflush(stdout); +} + +#define REC_FUNC(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ + MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \ + CALLFunc((uptr)psx##f); \ +/* branch = 2; */\ +} + +#define REC_SYS(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ + MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \ + CALLFunc((uptr)psx##f); \ + branch = 2; \ + iRet(); \ +} + +#define REC_BRANCH(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ + MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \ + CALLFunc((uptr)psx##f); \ + branch = 2; \ + iRet(); \ +} + +static void recRecompile(); + +static int recInit() { + int i; + + psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr)); + + recMem = mmap(0, + RECMEM_SIZE + PTRMULT*0x1000, + PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + recRAM = mmap(0, + 0x280000*PTRMULT, + PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + recROM = &recRAM[0x200000*PTRMULT]; + + if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) { + SysMessage("Error allocating memory"); return -1; + } + memset(recMem, 0, RECMEM_SIZE); + memset(recRAM, 0, 0x200000 * PTRMULT); + memset(recROM, 0, 0x080000 * PTRMULT); + + for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (uptr)&recRAM[PTRMULT*((i & 0x1f) << 16)]; + memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * sizeof(uptr)); + memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * sizeof(uptr)); + + for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (uptr)&recROM[PTRMULT*(i << 16)]; + + return 0; +} + +static void recReset() { + memset(recRAM, 0, 0x200000 * PTRMULT); + memset(recROM, 0, 0x080000 * PTRMULT); + + //x86Init(); + cpudetectInit(); + x86SetPtr(recMem); + + branch = 0; + memset(iRegs, 0, sizeof(iRegs)); + iRegs[0].state = ST_CONST; + iRegs[0].k = 0; +} + +static void recShutdown() { + if (recMem == NULL) return; + free(psxRecLUT); + munmap(recMem, RECMEM_SIZE + PTRMULT*0x1000); + munmap(recRAM, 0x280000*PTRMULT); + x86Shutdown(); +} + +static void recError() { + SysReset(); + ClosePlugins(); + SysMessage("Unrecoverable error while running recompiler\n"); + SysRunGui(); +} + +/*__inline*/ static void execute() { + void (*recFunc)(); + uptr *p; + + p = (uptr *)PC_REC(psxRegs.pc); + // if (!p) { recError(); return; } + + if (*p == 0) { + recRecompile(); + } + + if (*p < (uptr)recMem || *p >= (uptr)recMem + RECMEM_SIZE) + { + recError(); + return; + } + recFunc = (void (*)())*p; + (*recFunc)(); +} + +static void recExecute() { + for (;;) execute(); +} + +static void recExecuteBlock() { + execute(); +} + +static void recClear(u32 Addr, u32 Size) { + memset((void *)PC_REC(Addr), 0, Size * sizeof(uptr)); +} + +static void recNULL() { +// SysMessage("recUNK: %8.8x\n", psxRegs.code); +} + +/********************************************************* +* goes to opcodes tables... * +* Format: table[something....] * +*********************************************************/ + +//REC_SYS(SPECIAL); +#if 1 +static void recSPECIAL() { + recSPC[_Funct_](); +} +#endif + +static void recREGIMM() { + recREG[_Rt_](); +} + +static void recCOP0() { + recCP0[_Rs_](); +} + +//REC_SYS(COP2); +#if 1 +static void recCOP2() { + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); + AND32ItoR(EAX, 0x40000000); + j32Ptr[31] = JZ32(0); + + recCP2[_Funct_](); + + x86SetJ32(j32Ptr[31]); +} +#endif + +static void recBASIC() { + recCP2BSC[_Rs_](); +} + +//end of Tables opcodes... + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +#if 0 +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); +REC_FUNC(SLTI); +REC_FUNC(SLTIU); +#endif + +#if 1 +static void recADDIU() { +// Rt = Rs + Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k+= _Imm_; + } else { + if (_Imm_ == 1) { + INC32M((uptr)&psxRegs.GPR.r[_Rt_]); + } else if (_Imm_ == -1) { + DEC32M((uptr)&psxRegs.GPR.r[_Rt_]); + } else if (_Imm_) { + ADD32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _Imm_); + } + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k + _Imm_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_ == 1) { + INC32R(EAX); + } else if (_Imm_ == -1) { + DEC32R(EAX); + } else if (_Imm_) { + ADD32ItoR(EAX, _Imm_); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} + +static void recADDI() { +// Rt = Rs + Im + recADDIU(); +} + +static void recSLTI() { +// Rt = Rs < Im (signed) + if (!_Rt_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, _Imm_); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +} + +static void recSLTIU() { +// Rt = Rs < Im (unsigned) + if (!_Rt_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, _Imm_); + SETB8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +} + +static void recANDI() { +// Rt = Rs And Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k&= _ImmU_; + } else { + AND32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_); + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + AND32ItoR(EAX, _ImmU_); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} + +static void recORI() { +// Rt = Rs Or Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k|= _ImmU_; + } else { + OR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_); + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_ImmU_) OR32ItoR (EAX, _ImmU_); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} + +static void recXORI() { +// Rt = Rs Xor Im + if (!_Rt_) return; + +// iFlushRegs(); + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k^= _ImmU_; + } else { + XOR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_); + } + } else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_); + } else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + XOR32ItoR(EAX, _ImmU_); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + } +} +#endif +//end of * Arithmetic with immediate operand + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +//REC_FUNC(LUI); +#if 1 +static void recLUI() { +// Rt = Imm << 16 + if (!_Rt_) return; + + MapConst(_Rt_, psxRegs.code << 16); +} +#endif +//End of Load Higher ..... + + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + + +#if 0 +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); +#endif + +#if 1 +static void recADDU() { +// Rd = Rs + Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rt_ == _Rd_) { + if (iRegs[_Rs_].k == 1) { + INC32M((uptr)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rs_].k == -1) { + DEC32M((uptr)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rs_].k) { + ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k); + } + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + if (iRegs[_Rs_].k == 1) { + INC32R(EAX); + } else if (iRegs[_Rs_].k == 0xffffffff) { + DEC32R(EAX); + } else if (iRegs[_Rs_].k) { + ADD32ItoR(EAX, iRegs[_Rs_].k); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rs_ == _Rd_) { + if (iRegs[_Rt_].k == 1) { + INC32M((uptr)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rt_].k == -1) { + DEC32M((uptr)&psxRegs.GPR.r[_Rd_]); + } else if (iRegs[_Rt_].k) { + ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k); + } + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (iRegs[_Rt_].k == 1) { + INC32R(EAX); + } else if (iRegs[_Rt_].k == 0xffffffff) { + DEC32R(EAX); + } else if (iRegs[_Rt_].k) { + ADD32ItoR(EAX, iRegs[_Rt_].k); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + } else { + iRegs[_Rd_].state = ST_UNK; + + if (_Rs_ == _Rd_) { // Rd+= Rt + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (_Rt_ == _Rd_) { // Rd+= Rs + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { // Rd = Rs + Rt + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + } +} + +static void recADD() { +// Rd = Rs + Rt + recADDU(); +} + +static void recSUBU() { +// Rd = Rs - Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + SUB32ItoR(EAX, iRegs[_Rt_].k); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSUB() { +// Rd = Rs - Rt + recSUBU(); +} + +static void recAND() { +// Rd = Rs And Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rd_ == _Rt_) { // Rd&= Rs + AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k); + } else { + MOV32ItoR(EAX, iRegs[_Rs_].k); + AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + if (_Rd_ == _Rs_) { // Rd&= kRt + AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k); + } else { // Rd = Rs & kRt + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + AND32ItoR(EAX, iRegs[_Rt_].k); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + } else { + iRegs[_Rd_].state = ST_UNK; + + if (_Rs_ == _Rd_) { // Rd&= Rt + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (_Rt_ == _Rd_) { // Rd&= Rs + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { // Rd = Rs & Rt + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + } +} + +static void recOR() { +// Rd = Rs Or Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + OR32ItoR (EAX, iRegs[_Rt_].k); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recXOR() { +// Rd = Rs Xor Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + XOR32ItoR(EAX, iRegs[_Rt_].k); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recNOR() { +// Rd = Rs Nor Rt + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k)); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + NOT32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + OR32ItoR (EAX, iRegs[_Rt_].k); + NOT32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + NOT32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSLT() { +// Rd = Rs < Rt (signed) + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, iRegs[_Rt_].k); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + 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); + } +} + +static void recSLTU() { +// Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rs_].k); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32ItoR(EAX, iRegs[_Rt_].k); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + 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); + } +} +#endif +//End of * Register arithmetic + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +#if 0 +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC(DIV); +REC_FUNC(DIVU); +#endif + +#if 1 +static void recMULT() { +// Lo/Hi = Rs * Rt (signed) + +// iFlushRegs(); + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || + (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { + XOR32RtoR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + return; + } + + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k); + IMUL32R (EDX); + } else { + IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + } + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +static void recMULTU() { +// Lo/Hi = Rs * Rt (unsigned) + +// iFlushRegs(); + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || + (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { + XOR32RtoR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + return; + } + + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k); + MUL32R (EDX); + } else { + MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + } + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +static void recDIV() { +// Lo/Hi = Rs / Rt (signed) + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + if (iRegs[_Rt_].k == 0) { + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } + return; + } + MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + } + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } + CDQ(); + IDIV32R (ECX); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + if (!IsConst(_Rt_)) { + j8Ptr[1] = JMP8(1); + + x86SetJ8(j8Ptr[0]); + + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } + + x86SetJ8(j8Ptr[1]); + } +} + +static void recDIVU() { +// Lo/Hi = Rs / Rt (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + if (iRegs[_Rt_].k == 0) { + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } + return; + } + MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + } + if (IsConst(_Rs_)) { + MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } + XOR32RtoR(EDX, EDX); + DIV32R (ECX); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + if (!IsConst(_Rt_)) { + j8Ptr[1] = JMP8(1); + + x86SetJ8(j8Ptr[0]); + + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } + + x86SetJ8(j8Ptr[1]); + } +} +#endif +//End of * Register mult/div & Register trap logic + +#if 0 +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); + +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); +#endif + + +static void SetArg_OfB(x86IntRegType arg) { + if (IsConst(_Rs_)) +#ifdef __x86_64__ + MOV64ItoR(arg, iRegs[_Rs_].k + _Imm_); +#else + PUSH32I (iRegs[_Rs_].k + _Imm_); +#endif + else { +#ifdef __x86_64__ + MOV32MtoR(arg, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) + ADD32ItoR(arg, _Imm_); +#else + if (_Imm_) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + } else { + PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]); + } +#endif + } +#ifndef __x86_64__ + resp += 4; +#endif +} + +#if 1 +static void recLB() { +// Rt = mem[Rs + Im] (signed) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRs8(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } +// SysPrintf("unhandled r8 %x\n", addr); + } + + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemRead8); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVSX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); +} + +static void recLBU() { +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu8(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } +// SysPrintf("unhandled r8u %x\n", addr); + } + + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemRead8); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVZX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); +} + +static void recLH() { +// Rt = mem[Rs + Im] (signed) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRs16(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVSX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } +// SysPrintf("unhandled r16 %x\n", addr); + } + + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemRead16); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVSX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); +} + +static void recLHU() { +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu16(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80) { + if (addr >= 0x1f801c00 && addr < 0x1f801e00) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + //PUSHI (addr); + MOV64ItoR(X86ARG1, addr); + //CALLFunc ((uptr)SPU_readRegister); + MOV64ItoR(RAX, (uptr)SPU_readRegister); + CALL64R(RAX); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +#ifndef __WIN32__ + resp+= 4; +#endif + return; + } + switch (addr) { + case 0x1f801100: case 0x1f801110: case 0x1f801120: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + //PUSHI((addr >> 4) & 0x3); + MOV64ItoR(X86ARG1, (addr >> 4) & 0x3); + CALLFunc((uptr)psxRcntRcount); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + resp+= 4; + return; + + case 0x1f801104: case 0x1f801114: case 0x1f801124: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV64ItoR(X86ARG1, (addr >> 4) & 0x3); + CALLFunc((uptr)psxRcntRmode); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + resp+= 4; + return; + + case 0x1f801108: case 0x1f801118: case 0x1f801128: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV64ItoR(X86ARG1, (addr >> 4) & 0x3); + CALLFunc((uptr)psxRcntRtarget); + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + resp+= 4; + return; + } + } +// SysPrintf("unhandled r16u %x\n", addr); + } + + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemRead16); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); +} + +static void recLW() { +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu32(addr)); + return; + } + if ((t & 0x1fe0) == 0) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80) { + switch (addr) { + case 0x1f801080: case 0x1f801084: case 0x1f801088: + case 0x1f801090: case 0x1f801094: case 0x1f801098: + case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8: + case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8: + case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8: + case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8: + case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8: + case 0x1f801070: case 0x1f801074: + case 0x1f8010f0: case 0x1f8010f4: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + + case 0x1f801810: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + CALLFunc((uptr)GPU_readData); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + + case 0x1f801814: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + CALLFunc((uptr)GPU_readStatus); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } +// SysPrintf("unhandled r32 %x\n", addr); + } + + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemRead32); + if (_Rt_) { + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } +// ADD32ItoR(ESP, 4); +} + +extern u32 LWL_MASK[4]; +extern u32 LWL_SHIFT[4]; + +void iLWLk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + AND32ItoR(ECX, LWL_MASK[shift]); + SHL32ItoR(EAX, LWL_SHIFT[shift]); + OR32RtoR (EAX, ECX); +} + +void recLWL() { +// Rt = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0) { + MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); + iLWLk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); + iLWLk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + //PUSH64R (EAX); + AND32ItoR(EAX, ~3); + //PUSH64R (EAX); + MOV32RtoR(X86ARG1, EAX); + CALLFunc((uptr)psxMemRead32); + + if (_Rt_) { + //ADD32ItoR(ESP, 4); + //POP64R (EDX); + if (IsConst(_Rs_)) MOV32ItoR(EDX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EDX, _Imm_); + } + + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV64ItoR(ECX, (uptr)LWL_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift] + + MOV64ItoR(ECX, (uptr)LWL_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift] + + OR32RtoR(EAX, EDX); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + //} else { + //ADD64ItoR(RSP, 8); + //resp+= 8; + } +} + +/* +static void recLWBlock(int count) { + u32 *code = PSXM(pc); + int i, respsave; +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + // since bios is readonly it won't change + for (i=0; i<count; i++, code++, addr+=4) { + if (_fRt_(*code)) { + MapConst(_fRt_(*code), psxRu32(addr)); + } + } + return; + } + if ((t & 0x1fe0) == 0) { + for (i=0; i<count; i++, code++, addr+=4) { + if (!_fRt_(*code)) return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + for (i=0; i<count; i++, code++, addr+=4) { + if (!_fRt_(*code)) return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + } + + SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_)); + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemPointer); +// ADD32ItoR(ESP, 4); + + respsave = resp; resp = 0; + TEST64RtoR(RAX,RAX); + j32Ptr[4] = JZ32(0); + XOR32RtoR(ECX, ECX); + for (i=0; i<count; i++, code++) { + if (_fRt_(*code)) { + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV64RmStoR(EDX, EAX, ECX, 2); + MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EDX); + } + if (i != (count-1)) INC32R(ECX); + } + j32Ptr[5] = JMP32(0); + x86SetJ32(j32Ptr[4]); + for (i=0, code = PSXM(pc); i<count; i++, code++) { + psxRegs.code = *code; + recLW(); + } +#ifndef __x86_64__ + ADD32ItoR(ESP, resp); +#endif + x86SetJ32(j32Ptr[5]); + resp = respsave; +} +*/ + +extern u32 LWR_MASK[4]; +extern u32 LWR_SHIFT[4]; + +void iLWRk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + AND32ItoR(ECX, LWR_MASK[shift]); + SHR32ItoR(EAX, LWR_SHIFT[shift]); + OR32RtoR (EAX, ECX); +} + +void recLWR() { +// Rt = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0) { + MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); + iLWRk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); + iLWRk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSHR(EAX); + AND32ItoR(EAX, ~3); + MOV32RtoR(X86ARG1, EAX); + CALLFunc((uptr)psxMemRead32); + + POPR (EDX); + if (_Rt_) { + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV64ItoR(ECX, (uptr)LWR_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift] + + MOV64ItoR(ECX, (uptr)LWR_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift] + + OR32RtoR(EAX, EDX); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + //} else { + //resp+= 8; + } +} + +static void recSB() { +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV8ItoM((uptr)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k); + } else { + MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV8RtoM((uptr)&psxM[addr & 0x1fffff], EAX); + } + MOV32ItoR(X86ARG2, 1); + MOV32ItoR(X86ARG1, addr & ~3); + CALLFunc((uptr)&recClear); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV8ItoM((uptr)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k); + } else { + MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV8RtoM((uptr)&psxH[addr & 0xfff], EAX); + } + return; + } +// SysPrintf("unhandled w8 %x\n", addr); + } + + if (IsConst(_Rt_)) { + MOV64ItoR(X86ARG2, iRegs[_Rt_].k); + } else { + MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemWrite8); +// ADD32ItoR(ESP, 8); +} + +static void recSH() { +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV16ItoM((uptr)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k); + } else { + MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV16RtoM((uptr)&psxM[addr & 0x1fffff], EAX); + } + MOV32ItoR(X86ARG2, 1); + MOV32ItoR(X86ARG1, addr & ~3); + CALLFunc((uptr)&recClear); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV16ItoM((uptr)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k); + } else { + MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV16RtoM((uptr)&psxH[addr & 0xfff], EAX); + } + return; + } + if (t == 0x1f80) { + if (addr >= 0x1f801c00 && addr < 0x1f801e00) { + if (IsConst(_Rt_)) { + MOV64ItoR(X86ARG2, iRegs[_Rt_].k); + } else { + MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); + } + MOV64ItoR(X86ARG1, addr); + CALLFunc ((uptr)SPU_writeRegister); +#ifndef __WIN32__ + //resp+= 8; +#endif + return; + } + } +// SysPrintf("unhandled w16 %x\n", addr); + } + + if (IsConst(_Rt_)) { + MOV64ItoR(X86ARG2, iRegs[_Rt_].k); + } else { + MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemWrite16); +// ADD32ItoR(ESP, 8); +} + +static void recSW() { +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX); + } + MOV32ItoR(X86ARG2, 1); + MOV32ItoR(X86ARG1, addr); + CALLFunc((uptr)&recClear); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV32ItoM((uptr)&psxH[addr & 0xfff], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxH[addr & 0xfff], EAX); + } + return; + } + if (t == 0x1f80) { + switch (addr) { + case 0x1f801080: case 0x1f801084: + case 0x1f801090: case 0x1f801094: + case 0x1f8010a0: case 0x1f8010a4: + case 0x1f8010b0: case 0x1f8010b4: + case 0x1f8010c0: case 0x1f8010c4: + case 0x1f8010d0: case 0x1f8010d4: + case 0x1f8010e0: case 0x1f8010e4: + case 0x1f801074: + case 0x1f8010f0: + if (IsConst(_Rt_)) { + MOV32ItoM((uptr)&psxH[addr & 0xffff], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxH[addr & 0xffff], EAX); + } + return; + + case 0x1f801810: + if (IsConst(_Rt_)) { + MOV64ItoR(X86ARG1, iRegs[_Rt_].k); + } else { + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]); + } + CALLFunc((uptr)GPU_writeData); +#ifndef __WIN32__ + //resp+= 4; +#endif + return; + + case 0x1f801814: + if (IsConst(_Rt_)) { + MOV64ItoR(X86ARG1, iRegs[_Rt_].k); + } else { + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]); + } + CALLFunc((uptr)GPU_writeStatus); +#ifndef __WIN32__ + //resp+= 4; +#endif + } + } +// SysPrintf("unhandled w32 %x\n", addr); + } + + if (IsConst(_Rt_)) { + MOV64ItoR(X86ARG2, iRegs[_Rt_].k); + } else { + MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemWrite32); +// ADD32ItoR(ESP, 8); + //resp+= 8; +} + +/* +static void recSWBlock(int count) { + u32 *code; + int i, respsave; +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + code = PSXM(pc); + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + for (i=0; i<count; i++, code++, addr+=4) { + if (IsConst(_fRt_(*code))) { + MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]); + MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX); + } + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + for (i=0; i<count; i++, code++, addr+=4) { + if (!_fRt_(*code)) return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + } + + SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_)); + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemPointer); +// ADD32ItoR(ESP, 4); + //resp+= 4; + + respsave = resp; resp = 0; + TEST64RtoR(RAX,RAX); + j32Ptr[4] = JZ32(0); + XOR32RtoR(ECX, ECX); + for (i=0, code = PSXM(pc); i<count; i++, code++) { + if (IsConst(_fRt_(*code))) { + MOV32ItoR(EDX, iRegs[_fRt_(*code)].k); + } else { + MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]); + } + MOV32RtoRmS(EAX, ECX, 2, EDX); + if (i != (count-1)) INC32R(ECX); + } + j32Ptr[5] = JMP32(0); + x86SetJ32(j32Ptr[4]); + for (i=0, code = PSXM(pc); i<count; i++, code++) { + psxRegs.code = *code; + recSW(); + } + //ADD32ItoR(ESP, resp); + x86SetJ32(j32Ptr[5]); + resp = respsave; +} +*/ + +extern u32 SWL_MASK[4]; +extern u32 SWL_SHIFT[4]; + +void iSWLk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SHR32ItoR(ECX, SWL_SHIFT[shift]); + AND32ItoR(EAX, SWL_MASK[shift]); + OR32RtoR (EAX, ECX); +} + +void recSWL() { +// mem[Rs + Im] = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); + iSWLk(addr & 3); + MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); + iSWLk(addr & 3); + MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSHR (EAX); + AND32ItoR(EAX, ~3); + MOV32RtoR(X86ARG1, EAX); + + CALLFunc((uptr)psxMemRead32); + + POPR (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV64ItoR(ECX, (uptr)SWL_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift] + + MOV64ItoR(ECX, (uptr)SWL_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift] + + OR32RtoR (EAX, EDX); + MOV32RtoR(X86ARG2, EAX); + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + AND32ItoR(EAX, ~3); + MOV32RtoR(X86ARG1, EAX); + + CALLFunc((uptr)psxMemWrite32); +// ADD32ItoR(ESP, 8); + //resp+= 8; +} + +extern u32 SWR_MASK[4]; +extern u32 SWR_SHIFT[4]; + +void iSWRk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SHL32ItoR(ECX, SWR_SHIFT[shift]); + AND32ItoR(EAX, SWR_MASK[shift]); + OR32RtoR (EAX, ECX); +} + +void recSWR() { +// mem[Rs + Im] = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); + iSWRk(addr & 3); + MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); + iSWRk(addr & 3); + MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSHR (EAX); + + AND32ItoR(EAX, ~3); + MOV32RtoR(X86ARG1, EAX); + + CALLFunc((uptr)psxMemRead32); + + POPR (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV64ItoR(ECX, (uptr)SWR_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift] + + MOV64ItoR(ECX, (uptr)SWR_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift] + + OR32RtoR (EAX, EDX); + MOV32RtoR(X86ARG2, EAX); + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + AND32ItoR(EAX, ~3); + MOV32RtoR(X86ARG1, EAX); + CALLFunc((uptr)psxMemWrite32); +// ADD32ItoR(ESP, 8); + //resp+= 8; +} + +#endif + +#if 0 +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +#endif +#if 1 +static void recSLL() { +// Rd = Rt << Sa + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rt_].k << _Sa_); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + if (_Sa_) SHL32ItoR(EAX, _Sa_); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRL() { +// Rd = Rt >> Sa + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + if (_Sa_) SHR32ItoR(EAX, _Sa_); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRA() { +// Rd = Rt >> Sa + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + if (_Sa_) SAR32ItoR(EAX, _Sa_); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} +#endif + +#if 0 +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +#endif + +#if 1 +static void recSLLV() { +// Rd = Rt << Rs + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32ItoR(ECX, iRegs[_Rs_].k); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rt_].k); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRLV() { +// Rd = Rt >> Rs + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32ItoR(ECX, iRegs[_Rs_].k); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rt_].k); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +static void recSRAV() { +// Rd = Rt >> Rs + if (!_Rd_) return; + +// iFlushRegs(); + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k); + } else if (IsConst(_Rs_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32ItoR(ECX, iRegs[_Rs_].k); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else if (IsConst(_Rt_)) { + iRegs[_Rd_].state = ST_UNK; + + MOV32ItoR(EAX, iRegs[_Rt_].k); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } else { + iRegs[_Rd_].state = ST_UNK; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} +#endif + +#if 0 +REC_SYS(SYSCALL); +REC_SYS(BREAK); +#endif + +int dump = 0; + +#if 1 +static void recSYSCALL() { +// dump=1; + iFlushRegs(); + + MOV32ItoR(EAX, pc - 4); + MOV32RtoM((uptr)&psxRegs.pc, EAX); + MOV64ItoR(X86ARG2, branch == 1 ? 1 : 0); + MOV64ItoR(X86ARG1, 0x20); + CALLFunc((uptr)psxException); + //ADD32ItoR(ESP, 8); + + branch = 2; + iRet(); +} + +static void recBREAK() { +} +#endif + +#if 0 +REC_FUNC(MFHI); +REC_FUNC(MTHI); +REC_FUNC(MFLO); +REC_FUNC(MTLO); +#endif +#if 1 +static void recMFHI() { +// Rd = Hi + if (!_Rd_) return; + + iRegs[_Rd_].state = ST_UNK; + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +static void recMTHI() { +// Hi = Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } +} + +static void recMFLO() { +// Rd = Lo + if (!_Rd_) return; + + iRegs[_Rd_].state = ST_UNK; + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +static void recMTLO() { +// Lo = Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + } +} +#endif + +#if 0 +REC_BRANCH(J); +REC_BRANCH(JR); +REC_BRANCH(JAL); +REC_BRANCH(JALR); +REC_BRANCH(BLTZ); +REC_BRANCH(BGTZ); +REC_BRANCH(BLTZAL); +REC_BRANCH(BGEZAL); +REC_BRANCH(BNE); +REC_BRANCH(BEQ); +REC_BRANCH(BLEZ); +REC_BRANCH(BGEZ); +#endif +#if 1 +static void recBLTZ() { +// Branch if Rs < 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k < 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JL32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBGTZ() { +// Branch if Rs > 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k > 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JG32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBLTZAL() { +// Branch if Rs < 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k < 0) { + MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JL32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); + iBranch(bpc, 0); + pc+=4; +} + +static void recBGEZAL() { +// Branch if Rs >= 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k >= 0) { + MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JGE32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); + iBranch(bpc, 0); + pc+=4; +} + +static void recJ() { +// j target + + iJump(_Target_ * 4 + (pc & 0xf0000000)); +} + +static void recJAL() { +// jal target + + MapConst(31, pc + 4); + + iJump(_Target_ * 4 + (pc & 0xf0000000)); +} + +static void recJR() { +// jr Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&target, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&target, EAX); + } + + SetBranch(); +} + +static void recJALR() { +// jalr Rs + + if (IsConst(_Rs_)) { + MOV32ItoM((uptr)&target, iRegs[_Rs_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&target, EAX); + } + + if (_Rd_) { + MapConst(_Rd_, pc + 4); + } + + SetBranch(); +} + +static void recBEQ() { +// Branch if Rs == Rt + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (_Rs_ == _Rt_) { + iJump(bpc); + } else { + if (IsConst(_Rs_) && IsConst(_Rt_)) { + if (iRegs[_Rs_].k == iRegs[_Rt_].k) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } else if (IsConst(_Rs_)) { + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k); + } else if (IsConst(_Rt_)) { + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + + j32Ptr[4] = JE32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; + } +} + +static void recBNE() { +// Branch if Rs != Rt + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + if (iRegs[_Rs_].k != iRegs[_Rt_].k) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } else if (IsConst(_Rs_)) { + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k); + } else if (IsConst(_Rt_)) { + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } + j32Ptr[4] = JNE32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBLEZ() { +// Branch if Rs <= 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k <= 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JLE32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBGEZ() { +// Branch if Rs >= 0 + u32 bpc = _Imm_ * 4 + pc; + +// iFlushRegs(); + if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { + return; + } + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k >= 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + j32Ptr[4] = JGE32(0); + + iBranch(pc+4, 1); + + x86SetJ32(j32Ptr[4]); + + iBranch(bpc, 0); + pc+=4; +} +#endif + +#if 0 +REC_FUNC(MFC0); +REC_SYS(MTC0); +REC_FUNC(CFC0); +REC_SYS(CTC0); +REC_FUNC(RFE); +#endif +//REC_SYS(MTC0); +#if 1 +static void recMFC0() { +// Rt = Cop0->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +static void recCFC0() { +// Rt = Cop0->Rd + + recMFC0(); +} + +//* +void psxMTC0(); +static void recMTC0() { +// Cop0->Rd = Rt + + if (IsConst(_Rt_)) { + switch (_Rd_) { + case 12: + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); + break; + case 13: + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00)); + break; + default: + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); + break; + } + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + switch (_Rd_) { + case 13: + AND32ItoR(EAX, ~(0xfc00)); + break; + } + MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX); + } + + if (_Rd_ == 12 || _Rd_ == 13) { + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); + CALLFunc((uptr)psxTestSWInts); + if (branch == 0) { + branch = 2; + iRet(); + } + } +}//*/ + +static void recCTC0() { +// Cop0->Rd = Rt + + recMTC0(); +} + +static void recRFE() { + 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); + + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); + CALLFunc((uptr)psxTestSWInts); + if (branch == 0) { + branch = 2; + iRet(); + } +} +#endif + +#include "iGte.h" + +// + +static void recHLE() { + iFlushRegs(); + + CALLFunc((uptr)psxHLEt[psxRegs.code & 0xffff]); + branch = 2; + iRet(); +} + +// + +static void (*recBSC[64])() = { + recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ, + recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI , + recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL, + recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL, + recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL, + recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL +}; + +static void (*recSPC[64])() = { + recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV, + recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL, + recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL, + recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL, + recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR , + recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL +}; + +static void (*recREG[32])() = { + recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL +}; + +static void (*recCP0[32])() = { + recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL +}; + +static void (*recCP2[64])() = { + recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00 + recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08 + recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10 + recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18 + recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20 + recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28 + recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30 + recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38 +}; + +static void (*recCP2BSC[32])() = { + recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, 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 +}; + + +static void recRecompile() { + char *p; + char *ptr; + + dump = 0; + resp = 0; + + /* if x86Ptr reached the mem limit reset whole mem */ + if (((uptr)x86Ptr - (uptr)recMem) >= (RECMEM_SIZE - PTRMULT*0x10000)) + recReset(); + + x86Align(32); + ptr = x86Ptr; + + PC_RECP(psxRegs.pc) = (uptr)x86Ptr; + pc = psxRegs.pc; + pcold = pc; + + //Make some stack space for function arguments spill (x86-64 calling conventions) + // 0x38 = 7 args, should be plenty... + SUB64ItoR(RSP, STACKSIZE); + + for (count=0; count<500;) { + p = (char *)PSXM(pc); + if (p == NULL) recError(); + psxRegs.code = *(u32 *)p; +/* + if ((psxRegs.code >> 26) == 0x23) { // LW + int i; + u32 code; + + for (i=1;; i++) { + p = (char *)PSXM(pc+i*4); + if (p == NULL) recError(); + code = *(u32 *)p; + + if ((code >> 26) != 0x23 || + _fRs_(code) != _Rs_ || + _fImm_(code) != (_Imm_+i*4)) + break; + } + if (i > 1) { + recLWBlock(i); + pc = pc + i*4; continue; + } + } + + if ((psxRegs.code >> 26) == 0x2b) { // SW + int i; + u32 code; + + for (i=1;; i++) { + p = (char *)PSXM(pc+i*4); + if (p == NULL) recError(); + code = *(u32 *)p; + + if ((code >> 26) != 0x2b || + _fRs_(code) != _Rs_ || + _fImm_(code) != (_Imm_+i*4)) + break; + } + if (i > 1) { + recSWBlock(i); + pc = pc + i*4; continue; + } + }*/ + + pc+=4; count++; + recBSC[psxRegs.code>>26](); + + if (branch) { + branch = 0; + if (dump) iDumpBlock(ptr); + return; + } + } + + iFlushRegs(); + + MOV32ItoM((uptr)&psxRegs.pc, pc); + iRet(); +} + + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; +#endif diff --git a/libpcsxcore/ix86_64/ix86-64.c b/libpcsxcore/ix86_64/ix86-64.c index 3a88d3cb..f48b742e 100644..100755 --- a/libpcsxcore/ix86_64/ix86-64.c +++ b/libpcsxcore/ix86_64/ix86-64.c @@ -1,3143 +1,3143 @@ -/*
- * ix86 core v0.6.2
- * Authors: linuzappz <linuzappz@pcsx.net>
- * alexey silinov
- * goldfinger
- * zerofrog(@gmail.com)
- */
-
-#ifdef __x86_64__
-
-// stop compiling if NORECBUILD build (only for Visual Studio)
-#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include "ix86-64.h"
-
-#ifdef __x86_64__
-
-#ifdef _MSC_VER
-// visual studio calling convention
-x86IntRegType g_x86savedregs[] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15 };
-x86IntRegType g_x86tempregs[] = { R8, R9, R10, R11, RDX, RCX };
-
-// arranged in savedreg -> tempreg order
-x86IntRegType g_x86allregs[14] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15, R8, R9, R10, R11, RDX, RCX };
-
-#else
-// standard calling convention
-
-// registers saved by called functions (no need to flush them across calls)
-x86IntRegType g_x86savedregs[] = { RBX, RBP, R12, R13, R14, R15 };
-// temp registers that need to be saved across calls
-x86IntRegType g_x86tempregs[] = { RCX, RDX, R8, R9, R10, R11, RSI, RDI };
-
-// arranged in savedreg -> tempreg order
-x86IntRegType g_x86allregs[14] = { RBX, RBP, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11, RSI, RDI };
-
-#endif
-
-x86IntRegType g_x868bitregs[11] = { RBX, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11 };
-x86IntRegType g_x86non8bitregs[3] = { RBP, RSI, RDI };
-
-#endif // __x86_64__
-
-s8 *x86Ptr;
-u8 *j8Ptr[32];
-u32 *j32Ptr[32];
-
-void WriteRmOffset(x86IntRegType to, int offset)
-{
- if( (to&7) == ESP ) {
- if( offset == 0 ) {
- ModRM( 0, 0, 4 );
- ModRM( 0, ESP, 4 );
- }
- else if( offset < 128 && 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 && offset >= -128 ) {
- ModRM( 1, 0, to );
- write8(offset);
- }
- else {
- ModRM( 2, 0, to );
- write32(offset);
- }
- }
-}
-
-void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset)
-{
- if ((from&7) == ESP) {
- if( offset == 0 ) {
- ModRM( 0, to, 0x4 );
- SibSB( 0, 0x4, 0x4 );
- }
- else if( offset < 128 && offset >= -128 ) {
- ModRM( 1, to, 0x4 );
- SibSB( 0, 0x4, 0x4 );
- write8(offset);
- }
- else {
- ModRM( 2, to, 0x4 );
- SibSB( 0, 0x4, 0x4 );
- write32(offset);
- }
- }
- else {
- if( offset == 0 ) {
- ModRM( 0, to, from );
- }
- else if( offset < 128 && offset >= -128 ) {
- ModRM( 1, to, from );
- write8(offset);
- }
- else {
- ModRM( 2, to, from );
- write32(offset);
- }
- }
-}
-
-// This function is just for rec debugging purposes
-void CheckX86Ptr( void )
-{
-}
-
-void writeVAROP(unsigned opl, u64 op)
-{
- while (opl--)
- {
- write8(op & 0xFF);
- op >>= 8;
- }
-}
-
-#define writeVARROP(REX, opl, op) ({ \
- if (opl > 1 && ((op & 0xFF) == 0x66 || (op & 0xFF) == 0xF3 || (op & 0xFF) == 0xF2)) { \
- write8(op & 0xFF); \
- opl --; \
- op >>= 8; \
- } \
- REX; \
- writeVAROP(opl, op); \
- })
-
-void MEMADDR_OP(bool w, unsigned opl, u64 op, bool isreg, int reg, uptr p, sptr off)
-{
-#ifdef __x86_64__
- sptr pr = MEMADDR_(p, 5 + opl + (w || reg >= 8) + off);
- if (SPTR32(pr))
- {
- writeVARROP(RexR(w, reg), opl, op);
- ModRM(0, reg, DISP32);
- write32(pr);
- }
- else if (UPTR32(p))
- {
- writeVARROP(RexR(w, reg), opl, op);
- ModRM(0, reg, SIB);
- SibSB(0, SIB, DISP32);
- write32(p);
- }
- else
- {
- assert(!isreg || reg != X86_TEMP);
- MOV64ItoR(X86_TEMP, p);
- writeVARROP(RexRB(w, reg, X86_TEMP), opl, op);
- ModRM(0, reg, X86_TEMP);
- }
-#else
- writeVARROP(RexR(w, reg), opl, op);
- ModRM(0, reg, DISP32);
- write32(p);
-#endif
-}
-
-void SET8R( int cc, int to )
-{
- RexB(0, 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 )
-{
- RexRB(0,to, from);
- write8( 0x0F );
- write8( cc );
- ModRM( 3, to, from );
-}
-
-void CMOV32MtoR( int cc, x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, cc), true, to, from, 0);
-}
-
-////////////////////////////////////////////////////
-void x86SetPtr( char* ptr )
-{
- x86Ptr = ptr;
-}
-
-////////////////////////////////////////////////////
-void x86Shutdown( void )
-{
-}
-
-////////////////////////////////////////////////////
-void x86SetJ8( u8* j8 )
-{
- u32 jump = ( x86Ptr - (s8*)j8 ) - 1;
-
- if ( jump > 0x7f ) {
- SysPrintf( "j8 greater than 0x7f!!\n" );
- assert(0);
- }
- *j8 = (u8)jump;
-}
-
-void x86SetJ8A( u8* j8 )
-{
- u32 jump = ( x86Ptr - (s8*)j8 ) - 1;
-
- if ( jump > 0x7f ) {
- SysPrintf( "j8 greater than 0x7f!!\n" );
- //assert(0);
- }
-
- if( ((uptr)x86Ptr&0xf) > 4 ) {
-
- uptr newjump = jump + 16-((uptr)x86Ptr&0xf);
-
- if( newjump <= 0x7f ) {
- jump = newjump;
- while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
- }
- }
- *j8 = (u8)jump;
-}
-
-void x86SetJ16( u16 *j16 )
-{
- // doesn't work
- u32 jump = ( x86Ptr - (s8*)j16 ) - 2;
-
- if ( jump > 0x7fff ) {
- SysPrintf( "j16 greater than 0x7fff!!\n" );
- //assert(0);
- }
- *j16 = (u16)jump;
-}
-
-void x86SetJ16A( u16 *j16 )
-{
- if( ((uptr)x86Ptr&0xf) > 4 ) {
- while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
- }
- x86SetJ16(j16);
-}
-
-////////////////////////////////////////////////////
-void x86SetJ32( u32* j32 )
-{
- *j32 = ( x86Ptr - (s8*)j32 ) - 4;
-}
-
-void x86SetJ32A( u32* j32 )
-{
- while((uptr)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 )
-{
- RexRB(1, from, to);
- write8( 0x89 );
- ModRM( 3, from, to );
-}
-
-/* mov r64 to m64 */
-void MOV64RtoM( uptr to, x86IntRegType from )
-{
- if (from == RAX)
- {
- RexR(1, 0);
- write8(0xA3);
- write64(to);
- }
- else
- {
- MEMADDR_OP(1, VAROP1(0x89), true, from, to, 0);
- }
-}
-
-/* mov m64 to r64 */
-void MOV64MtoR( x86IntRegType to, uptr from )
-{
- if (to == RAX)
- {
- RexR(1, 0);
- write8(0xA1);
- write64(from);
- }
- else
- {
- MEMADDR_OP(1, VAROP1(0x8B), true, to, from, 0);
- }
-}
-
-/* mov imm32 to m64 */
-void MOV64I32toM(uptr to, u32 from )
-{
- MEMADDR_OP(1, VAROP1(0xC7), false, 0, to, 4);
- write32(from);
-}
-
-// mov imm64 to r64
-void MOV64ItoR( x86IntRegType to, u64 from)
-{
- RexB(1, to);
- write8( 0xB8 | (to & 0x7) );
- write64( from );
-}
-
-/* mov imm32 to r64 */
-void MOV64I32toR( x86IntRegType to, s32 from )
-{
- RexB(1, to);
- write8( 0xC7 );
- ModRM( 0, 0, to );
- write32( from );
-}
-
-// mov imm64 to [r64+off]
-void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset)
-{
- RexB(1,to);
- write8( 0xC7 );
- WriteRmOffset(to, offset);
- write32(from);
-}
-
-// mov [r64+offset] to r64
-void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(1, to, from);
- write8( 0x8B );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-/* mov [r64][r64*scale] to r64 */
-void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
- RexRXB(1, to, from2, from);
- write8( 0x8B );
- ModRM( 0, to, 0x4 );
- SibSB(scale, from2, from );
-}
-
-/* mov r64 to [r64+offset] */
-void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(1,from,to);
- write8( 0x89 );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-/* mov r64 to [r64][r64*scale] */
-void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
- RexRXB(1, to, from2, from);
- write8( 0x89 );
- ModRM( 0, to, 0x4 );
- SibSB(scale, from2, from );
-}
-
-
-/* mov r32 to r32 */
-void MOV32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0, from, to);
- write8( 0x89 );
- ModRM( 3, from, to );
-}
-
-/* mov r32 to m32 */
-void MOV32RtoM( uptr to, x86IntRegType from )
-{
- if (from == EAX)
- {
- write8(0xA3);
- write64(to);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0x89), true, from, to, 0);
- }
-}
-
-/* mov m32 to r32 */
-void MOV32MtoR( x86IntRegType to, uptr from )
-{
- if (to == RAX)
- {
- write8(0xA1);
- write64(from);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0x8B), true, to, from, 0);
- }
-}
-
-/* mov [r32] to r32 */
-void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) {
- RexRB(0, to, from);
- write8(0x8B);
- WriteRmOffsetFrom(to, from, 0);
-}
-
-void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) {
- RexRB(0, to, from);
- write8( 0x8B );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-/* mov [r32+r32*scale] to r32 */
-void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
- RexRXB(0,to,from2,from);
- write8( 0x8B );
- ModRM( 0, to, 0x4 );
- SibSB(scale, from2, from );
-}
-
-// mov r32 to [r32<<scale+from2]
-void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, int from2, int scale )
-{
- RexRXB(0,to,from1,0);
- write8( 0x8B );
- ModRM( 0, to, 0x4 );
- ModRM( scale, from1, 5);
- write32(from2);
-}
-
-/* mov r32 to [r32] */
-void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) {
- RexRB(0, from, to);
- if ((to&7) == 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) {
- RexRXB(0, to, from2, from);
- write8( 0x89 );
- ModRM( 0, to, 0x4 );
- SibSB(scale, from2, from );
-}
-
-/* mov imm32 to r32 */
-void MOV32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0, to);
- write8( 0xB8 | (to & 0x7) );
- write32( from );
-}
-
-/* mov imm32 to m32 */
-void MOV32ItoM(uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0xC7), false, 0, to, 4);
- write32(from);
-}
-
-// mov imm32 to [r32+off]
-void MOV32ItoRmOffset( x86IntRegType to, u32 from, int offset)
-{
- RexB(0,to);
- write8( 0xC7 );
- WriteRmOffset(to, offset);
- write32(from);
-}
-
-// mov r32 to [r32+off]
-void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
-{
- RexRB(0,from,to);
- write8( 0x89 );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-/* mov r16 to m16 */
-void MOV16RtoM(uptr to, x86IntRegType from )
-{
- if (from == EAX)
- {
- write8(0x66);
- write8(0xA3);
- write64(to);
- }
- else
- {
- MEMADDR_OP(0, VAROP2(0x66, 0x89), true, from, to, 0);
- }
-}
-
-/* mov m16 to r16 */
-void MOV16MtoR( x86IntRegType to, uptr from )
-{
- if (to == EAX)
- {
- write8(0x66);
- write8(0xA1);
- write64(from);
- }
- else
- {
- MEMADDR_OP(0, VAROP2(0x66, 0x8B), true, to, from, 0);
- }
-}
-
-void MOV16RmtoR( x86IntRegType to, x86IntRegType from)
-{
- write8( 0x66 );
- RexRB(0,to,from);
- write8( 0x8B );
- WriteRmOffsetFrom(to, from, 0);
-}
-
-void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- write8( 0x66 );
- RexRB(0,to,from);
- write8( 0x8B );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale )
-{
- write8(0x66);
- RexRXB(0,to,from1,0);
- write8( 0x8B );
- ModRM( 0, to, 0x4 );
- ModRM( scale, from1, 5);
- write32(from2);
-}
-
-void MOV16RtoRm(x86IntRegType to, x86IntRegType from)
-{
- write8( 0x66 );
- RexRB(0,from,to);
- write8( 0x89 );
- ModRM( 0, from, to );
-}
-
-/* mov imm16 to m16 */
-void MOV16ItoM( uptr to, u16 from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0xC7), false, 0, to, 2);
- write16( from );
-}
-
-/* mov r16 to [r32][r32*scale] */
-void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
- write8( 0x66 );
- RexRXB(0,to,from2,from);
- write8( 0x89 );
- ModRM( 0, to, 0x4 );
- SibSB(scale, from2, from );
-}
-
-void MOV16ItoR( x86IntRegType to, u16 from )
-{
- RexB(0, to);
- write16( 0xB866 | ((to & 0x7)<<8) );
- write16( from );
-}
-
-// mov imm16 to [r16+off]
-void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset)
-{
- write8(0x66);
- RexB(0,to);
- write8( 0xC7 );
- WriteRmOffset(to, offset);
- write16(from);
-}
-
-// mov r16 to [r16+off]
-void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
-{
- write8(0x66);
- RexRB(0,from,to);
- write8( 0x89 );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-/* mov r8 to m8 */
-void MOV8RtoM( uptr to, x86IntRegType from )
-{
- if (from == EAX)
- {
- write8(0xA2);
- write64(to);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0x88), true, from, to, 0);
- }
-}
-
-/* mov m8 to r8 */
-void MOV8MtoR( x86IntRegType to, uptr from )
-{
- if (to == EAX)
- {
- write8(0xA0);
- write64(from);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0x8A), true, to, from, 0);
- }
-}
-
-/* mov [r32] to r8 */
-void MOV8RmtoR(x86IntRegType to, x86IntRegType from)
-{
- RexRB(0,to,from);
- write8( 0x8A );
- WriteRmOffsetFrom(to, from, 0);
-}
-
-void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset)
-{
- RexRB(0,to,from);
- write8( 0x8A );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-void MOV8RtoRm(x86IntRegType to, x86IntRegType from)
-{
- RexRB(0,from,to);
- write8( 0x88 );
- WriteRmOffsetFrom(from, to, 0);
-}
-
-/* mov imm8 to m8 */
-void MOV8ItoM( uptr to, u8 from )
-{
- MEMADDR_OP(0, VAROP1(0xC6), false, 0, to, 1);
- write8( from );
-}
-
-// mov imm8 to r8
-void MOV8ItoR( x86IntRegType to, u8 from )
-{
- RexB(0, to);
- write8( 0xB0 | (to & 0x7) );
- write8( from );
-}
-
-// mov imm8 to [r8+off]
-void MOV8ItoRmOffset( x86IntRegType to, u8 from, int offset)
-{
- assert( to != ESP );
- RexB(0,to);
- write8( 0xC6 );
- WriteRmOffset(to,offset);
- write8(from);
-}
-
-// mov r8 to [r8+off]
-void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
-{
- assert( to != ESP );
- RexRB(0,from,to);
- write8( 0x88 );
- WriteRmOffsetFrom(from,to,offset);
-}
-
-/* movsx r8 to r32 */
-void MOVSX32R8toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xBE0F );
- ModRM( 3, to, from );
-}
-
-void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xBE0F );
- ModRM( 0, to, from );
-}
-
-void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(0,to,from);
- write16( 0xBE0F );
- WriteRmOffsetFrom(to,from,offset);
-}
-
-/* movsx m8 to r32 */
-void MOVSX32M8toR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xBE), true, to, from, 0);
-}
-
-/* movsx r16 to r32 */
-void MOVSX32R16toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xBF0F );
- ModRM( 3, to, from );
-}
-
-void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xBF0F );
- ModRM( 0, to, from );
-}
-
-void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(0,to,from);
- write16( 0xBF0F );
- WriteRmOffsetFrom(to,from,offset);
-}
-
-/* movsx m16 to r32 */
-void MOVSX32M16toR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xBF), true, to, from, 0);
-}
-
-/* movzx r8 to r32 */
-void MOVZX32R8toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xB60F );
- ModRM( 3, to, from );
-}
-
-void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xB60F );
- ModRM( 0, to, from );
-}
-
-void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(0,to,from);
- write16( 0xB60F );
- WriteRmOffsetFrom(to,from,offset);
-}
-
-/* movzx m8 to r32 */
-void MOVZX32M8toR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xB6), true, to, from, 0);
-}
-
-/* movzx r16 to r32 */
-void MOVZX32R16toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xB70F );
- ModRM( 3, to, from );
-}
-
-void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xB70F );
- ModRM( 0, to, from );
-}
-
-void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(0,to,from);
- write16( 0xB70F );
- WriteRmOffsetFrom(to,from,offset);
-}
-
-/* movzx m16 to r32 */
-void MOVZX32M16toR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xB7), true, to, from, 0);
-}
-
-#ifdef __x86_64__
-
-/* movzx r8 to r64 */
-void MOVZX64R8toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1,to,from);
- write16( 0xB60F );
- ModRM( 3, to, from );
-}
-
-void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1,to,from);
- write16( 0xB60F );
- ModRM( 0, to, from );
-}
-
-void MOVZX64Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(1,to,from);
- write16( 0xB60F );
- WriteRmOffsetFrom(to,from,offset);
-}
-
-/* movzx m8 to r64 */
-void MOVZX64M8toR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP2(0x0F, 0xB6), true, to, from, 0);
-}
-
-/* movzx r16 to r64 */
-void MOVZX64R16toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1,to,from);
- write16( 0xB70F );
- ModRM( 3, to, from );
-}
-
-void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1,to,from);
- write16( 0xB70F );
- ModRM( 0, to, from );
-}
-
-void MOVZX64Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
-{
- RexRB(1,to,from);
- write16( 0xB70F );
- WriteRmOffsetFrom(to,from,offset);
-}
-
-/* movzx m16 to r64 */
-void MOVZX64M16toR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP2(0x0F, 0xB7), true, to, from, 0);
-}
-#endif
-
-/* cmovbe r32 to r32 */
-void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from )
-{
- CMOV32RtoR( 0x46, to, from );
-}
-
-/* cmovbe m32 to r32*/
-void CMOVBE32MtoR( x86IntRegType to, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from )
-{
- CMOV32MtoR( 0x4E, to, from );
-}
-
-////////////////////////////////////
-// arithmetic instructions /
-////////////////////////////////////
-
-/* add imm32 to r64 */
-void ADD64ItoR( x86IntRegType to, u32 from )
-{
- RexB(1, to);
- if (from <= 0x7f)
- {
- write8(0x83);
- ModRM( 3, 0, to );
- write8(from);
- }
- else
- {
- if (to == RAX) {
- write8( 0x05 );
- } else {
- write8( 0x81 );
- ModRM( 3, 0, to );
- }
- write32( from );
- }
-}
-
-/* add m64 to r64 */
-void ADD64MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP1(0x03), true, to, from, 0);
-}
-
-/* add r64 to r64 */
-void ADD64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1, from, to);
- write8( 0x01 );
- ModRM( 3, from, to );
-}
-
-/* add imm32 to r32 */
-void ADD32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0, to);
- if ( to == EAX) {
- write8( 0x05 );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 0, to );
- }
- write32( from );
-}
-
-/* add imm32 to m32 */
-void ADD32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 0, to, 4);
- write32(from);
-}
-
-// add imm32 to [r32+off]
-void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset)
-{
- RexB(0,to);
- write8( 0x81 );
- WriteRmOffset(to,offset);
- write32(from);
-}
-
-/* add r32 to r32 */
-void ADD32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0, from, to);
- write8( 0x01 );
- ModRM( 3, from, to );
-}
-
-/* add r32 to m32 */
-void ADD32RtoM(uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x01), true, from, to, 0);
-}
-
-/* add m32 to r32 */
-void ADD32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x03), true, to, from, 0);
-}
-
-// add r16 to r16
-void ADD16RtoR( x86IntRegType to , x86IntRegType from )
-{
- write8(0x66);
- RexRB(0,to,from);
- write8( 0x03 );
- ModRM( 3, to, from );
-}
-
-/* add imm16 to r16 */
-void ADD16ItoR( x86IntRegType to, u16 from )
-{
- write8( 0x66 );
- RexB(0,to);
- if ( to == EAX)
- {
- write8( 0x05 );
- }
- else
- {
- write8( 0x81 );
- ModRM( 3, 0, to );
- }
- write16( from );
-}
-
-/* add imm16 to m16 */
-void ADD16ItoM( uptr to, u16 from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 0, to, 2);
- write16( from );
-}
-
-/* add r16 to m16 */
-void ADD16RtoM(uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x01), true, from, to, 0);
-}
-
-/* add m16 to r16 */
-void ADD16MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x03), true, to, from, 0);
-}
-
-// add m8 to r8
-void ADD8MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x02), true, to, from, 0);
-}
-
-/* adc imm32 to r32 */
-void ADC32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x15 );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 2, to );
- }
- write32( from );
-}
-
-/* adc imm32 to m32 */
-void ADC32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 2, to, 4);
- write32(from);
-}
-
-/* adc r32 to r32 */
-void ADC32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x11 );
- ModRM( 3, from, to );
-}
-
-/* adc m32 to r32 */
-void ADC32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x13), true, to, from, 0);
-}
-
-// adc r32 to m32
-void ADC32RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x11), true, from, to, 0);
-}
-
-
-#ifdef __x86_64__
-void INC32R( x86IntRegType to )
-{
- write8( 0xFF );
- ModRM(3,0,to);
-}
-#else
-/* inc r32 */
-void INC32R( x86IntRegType to )
-{
- X86_64ASSERT();
- write8( 0x40 + to );
-}
-#endif
-/* inc m32 */
-void INC32M( uptr to )
-{
- MEMADDR_OP(0, VAROP1(0xFF), false, 0, to, 0);
-}
-
-/* inc r16 */
-void INC16R( x86IntRegType to )
-{
- X86_64ASSERT();
- write8( 0x66 );
- write8( 0x40 + to );
-}
-
-/* inc m16 */
-void INC16M( uptr to )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 0, to, 0);
-}
-
-
-/* sub imm32 to r64 */
-void SUB64ItoR( x86IntRegType to, u32 from )
-{
- RexB(1, to);
- if (from <= 0x7f)
- {
- write8(0x83);
- ModRM( 3, 5, to );
- write8(from);
- }
- else
- {
- if ( to == RAX ) {
- write8( 0x2D );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 5, to );
- }
- write32( from );
- }
-}
-
-/* sub r64 to r64 */
-void SUB64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1, from, to);
- write8( 0x29 );
- ModRM( 3, from, to );
-}
-
-/* sub m64 to r64 */
-void SUB64MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP1(0x2B), true, to, from, 0);
-}
-
-/* sub imm32 to r32 */
-void SUB32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x2D );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 5, to );
- }
- write32( from );
-}
-
-/* sub imm32 to m32 */
-void SUB32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 5, to, 4);
- write32(from);
-}
-
-/* sub r32 to r32 */
-void SUB32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0, from, to);
- write8( 0x29 );
- ModRM( 3, from, to );
-}
-
-/* sub m32 to r32 */
-void SUB32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x2B), true, to, from, 0);
-}
-
-// sub r32 to m32
-void SUB32RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x29), true, from, to, 0);
-}
-
-// sub r16 to r16
-void SUB16RtoR( x86IntRegType to, u16 from )
-{
- write8(0x66);
- RexRB(0,to,from);
- write8( 0x2b );
- ModRM( 3, to, from );
-}
-
-/* sub imm16 to r16 */
-void SUB16ItoR( x86IntRegType to, u16 from ) {
- write8( 0x66 );
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x2D );
- } else {
- write8( 0x81 );
- ModRM( 3, 5, to );
- }
- write16( from );
-}
-
-/* sub imm16 to m16 */
-void SUB16ItoM( uptr to, u16 from ) {
- MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 5, to, 2);
- write16( from );
-}
-
-/* sub m16 to r16 */
-void SUB16MtoR( x86IntRegType to, uptr from ) {
- MEMADDR_OP(0, VAROP2(0x66, 0x2B), true, to, from, 0);
-}
-
-/* sbb r64 to r64 */
-void SBB64RtoR( x86IntRegType to, x86IntRegType from ) {
- RexRB(1, from,to);
- write8( 0x19 );
- ModRM( 3, from, to );
-}
-
-/* sbb imm32 to r32 */
-void SBB32ItoR( x86IntRegType to, u32 from ) {
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x1D );
- } else {
- write8( 0x81 );
- ModRM( 3, 3, to );
- }
- write32( from );
-}
-
-/* sbb imm32 to m32 */
-void SBB32ItoM( uptr to, u32 from ) {
- MEMADDR_OP(0, VAROP1(0x81), false, 3, to, 4);
- write32( from );
-}
-
-/* sbb r32 to r32 */
-void SBB32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x19 );
- ModRM( 3, from, to );
-}
-
-/* sbb m32 to r32 */
-void SBB32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x1B), true, to, from, 0);
-}
-
-/* sbb r32 to m32 */
-void SBB32RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x19), true, from, to, 0);
-}
-
-#ifdef __x86_64__
-void DEC32R( x86IntRegType to )
-{
- write8( 0xFF );
- ModRM(3,1,to);
-}
-#else
-/* dec r32 */
-void DEC32R( x86IntRegType to )
-{
- X86_64ASSERT();
- write8( 0x48 + to );
-}
-#endif
-
-/* dec m32 */
-void DEC32M( uptr to )
-{
- MEMADDR_OP(0, VAROP1(0xFF), false, 1, to, 0);
-}
-
-/* dec r16 */
-void DEC16R( x86IntRegType to )
-{
- X86_64ASSERT();
- write8( 0x66 );
- write8( 0x48 + to );
-}
-
-/* dec m16 */
-void DEC16M( uptr to )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 1, to, 0);
-}
-
-/* mul eax by r32 to edx:eax */
-void MUL32R( x86IntRegType from )
-{
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 4, from );
-}
-
-/* imul eax by r32 to edx:eax */
-void IMUL32R( x86IntRegType from )
-{
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 5, from );
-}
-
-/* mul eax by m32 to edx:eax */
-void MUL32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 4, from, 0);
-}
-
-/* imul eax by m32 to edx:eax */
-void IMUL32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 5, from, 0);
-}
-
-/* imul r32 by r32 to r32 */
-void IMUL32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write16( 0xAF0F );
- ModRM( 3, to, from );
-}
-
-/* div eax by r32 to edx:eax */
-void DIV32R( x86IntRegType from )
-{
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 6, from );
-}
-
-/* idiv eax by r32 to edx:eax */
-void IDIV32R( x86IntRegType from )
-{
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 7, from );
-}
-
-/* div eax by m32 to edx:eax */
-void DIV32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 6, from, 0);
-}
-
-/* idiv eax by m32 to edx:eax */
-void IDIV32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 7, from, 0);
-}
-
-////////////////////////////////////
-// shifting instructions /
-////////////////////////////////////
-
-/* shl imm8 to r64 */
-void SHL64ItoR( x86IntRegType to, u8 from )
-{
- RexB(1, to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- ModRM( 3, 4, to );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 4, to );
- write8( from );
-}
-
-/* shl cl to r64 */
-void SHL64CLtoR( x86IntRegType to )
-{
- RexB(1, to);
- write8( 0xD3 );
- ModRM( 3, 4, to );
-}
-
-/* shr imm8 to r64 */
-void SHR64ItoR( x86IntRegType to, u8 from )
-{
- RexB(1,to);
- if ( from == 1 ) {
- write8( 0xD1 );
- ModRM( 3, 5, to );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 5, to );
- write8( from );
-}
-
-/* shr cl to r64 */
-void SHR64CLtoR( x86IntRegType to )
-{
- RexB(1, to);
- write8( 0xD3 );
- ModRM( 3, 5, to );
-}
-
-/* shl imm8 to r32 */
-void SHL32ItoR( x86IntRegType to, u8 from )
-{
- RexB(0, to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- write8( 0xE0 | (to & 0x7) );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 4, to );
- write8( from );
-}
-
-/* shl imm8 to m32 */
-void SHL32ItoM( uptr to, u8 from )
-{
- if ( from == 1 )
- {
- MEMADDR_OP(0, VAROP1(0xD1), false, 4, to, 0);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0xC1), false, 4, to, 1);
- write8( from );
- }
-}
-
-/* shl cl to r32 */
-void SHL32CLtoR( x86IntRegType to )
-{
- RexB(0,to);
- write8( 0xD3 );
- ModRM( 3, 4, to );
-}
-
-// shl imm8 to r16
-void SHL16ItoR( x86IntRegType to, u8 from )
-{
- write8(0x66);
- RexB(0,to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- write8( 0xE0 | (to & 0x7) );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 4, to );
- write8( from );
-}
-
-// shl imm8 to r8
-void SHL8ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- 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 ) {
- RexB(0,to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- write8( 0xE8 | (to & 0x7) );
- }
- else
- {
- write8( 0xC1 );
- ModRM( 3, 5, to );
- write8( from );
- }
-}
-
-/* shr imm8 to m32 */
-void SHR32ItoM( uptr to, u8 from )
-{
- if ( from == 1 )
- {
- MEMADDR_OP(0, VAROP1(0xD1), false, 5, to, 0);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0xC1), false, 5, to, 1);
- write8( from );
- }
-}
-
-/* shr cl to r32 */
-void SHR32CLtoR( x86IntRegType to )
-{
- RexB(0,to);
- write8( 0xD3 );
- ModRM( 3, 5, to );
-}
-
-// shr imm8 to r8
-void SHR8ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- 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 )
-{
- RexB(1,to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- ModRM( 3, 7, to );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 7, to );
- write8( from );
-}
-
-/* sar cl to r64 */
-void SAR64CLtoR( x86IntRegType to )
-{
- RexB(1, to);
- write8( 0xD3 );
- ModRM( 3, 7, to );
-}
-
-/* sar imm8 to r32 */
-void SAR32ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- ModRM( 3, 7, to );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 7, to );
- write8( from );
-}
-
-/* sar imm8 to m32 */
-void SAR32ItoM( uptr to, u8 from )
-{
- if (from == 1)
- {
- MEMADDR_OP(0, VAROP1(0xD1), false, 7, to, 0);
- }
- else
- {
- MEMADDR_OP(0, VAROP1(0xC1), false, 7, to, 1);
- write8( from );
- }
-}
-
-/* sar cl to r32 */
-void SAR32CLtoR( x86IntRegType to )
-{
- RexB(0,to);
- write8( 0xD3 );
- ModRM( 3, 7, to );
-}
-
-// sar imm8 to r16
-void SAR16ItoR( x86IntRegType to, u8 from )
-{
- write8(0x66);
- RexB(0,to);
- if ( from == 1 )
- {
- write8( 0xD1 );
- ModRM( 3, 7, to );
- return;
- }
- write8( 0xC1 );
- ModRM( 3, 7, to );
- write8( from );
-}
-
-void ROR32ItoR( x86IntRegType to,u8 from )
-{
- RexB(0,to);
- if ( from == 1 ) {
- write8( 0xd1 );
- write8( 0xc8 | to );
- }
- else
- {
- write8( 0xc1 );
- write8( 0xc8 | to );
- write8( from );
- }
-}
-
-void RCR32ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- if ( from == 1 ) {
- write8( 0xd1 );
- write8( 0xd8 | to );
- }
- else
- {
- write8( 0xc1 );
- write8( 0xd8 | to );
- write8( from );
- }
-}
-
-// shld imm8 to r32
-void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
-{
- RexRB(0,from,to);
- write8( 0x0F );
- write8( 0xA4 );
- ModRM( 3, from, to );
- write8( shift );
-}
-
-// shrd imm8 to r32
-void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
-{
- RexRB(0,from,to);
- write8( 0x0F );
- write8( 0xAC );
- ModRM( 3, from, to );
- write8( shift );
-}
-
-////////////////////////////////////
-// logical instructions /
-////////////////////////////////////
-
-/* or imm32 to r32 */
-void OR64ItoR( x86IntRegType to, u32 from )
-{
- RexB(1, to);
- if ( to == EAX ) {
- write8( 0x0D );
- } else {
- write8( 0x81 );
- ModRM( 3, 1, to );
- }
- write32( from );
-}
-
-/* or m64 to r64 */
-void OR64MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP1(0x0B), true, to, from, 0);
-}
-
-/* or r64 to r64 */
-void OR64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1, from, to);
- write8( 0x09 );
- ModRM( 3, from, to );
-}
-
-// or r32 to m64
-void OR64RtoM(uptr to, x86IntRegType from )
-{
- MEMADDR_OP(1, VAROP1(0x09), true, from, to, 0);
-}
-
-/* or imm32 to r32 */
-void OR32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x0D );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 1, to );
- }
- write32( from );
-}
-
-/* or imm32 to m32 */
-void OR32ItoM(uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 1, to, 4);
- write32(from);
-}
-
-/* or r32 to r32 */
-void OR32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x09 );
- ModRM( 3, from, to );
-}
-
-/* or r32 to m32 */
-void OR32RtoM(uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x09), true, from, to, 0);
-}
-
-/* or m32 to r32 */
-void OR32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x0B), true, to, from, 0);
-}
-
-// or r16 to r16
-void OR16RtoR( x86IntRegType to, x86IntRegType from )
-{
- write8(0x66);
- RexRB(0,from,to);
- write8( 0x09 );
- ModRM( 3, from, to );
-}
-
-// or imm16 to r16
-void OR16ItoR( x86IntRegType to, u16 from )
-{
- write8(0x66);
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x0D );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 1, to );
- }
- write16( from );
-}
-
-// or imm16 to m316
-void OR16ItoM( uptr to, u16 from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 1, to, 2);
- write16( from );
-}
-
-/* or m16 to r16 */
-void OR16MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x0B), true, to, from, 0);
-}
-
-// or r16 to m16
-void OR16RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x09), true, from, to, 0);
-}
-
-// or r8 to r8
-void OR8RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x08 );
- ModRM( 3, from, to );
-}
-
-// or r8 to m8
-void OR8RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x08), true, from, to, 0);
-}
-
-// or imm8 to m8
-void OR8ItoM( uptr to, u8 from )
-{
- MEMADDR_OP(0, VAROP1(0x80), false, 1, to, 1);
- write8( from );
-}
-
-// or m8 to r8
-void OR8MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x0A), true, to, from, 0);
-}
-
-/* xor imm32 to r64 */
-void XOR64ItoR( x86IntRegType to, u32 from )
-{
- RexB(1,to);
- if ( to == EAX ) {
- write8( 0x35 );
- } else {
- write8( 0x81 );
- ModRM( 3, 6, to );
- }
- write32( from );
-}
-
-/* xor r64 to r64 */
-void XOR64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1, from, to);
- write8( 0x31 );
- ModRM( 3, from, to );
-}
-
-/* xor m64 to r64 */
-void XOR64MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP1(0x33), true, to, from, 0);
-}
-
-/* xor r64 to m64 */
-void XOR64RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(1, VAROP1(0x31), true, from, to, 0);
-}
-
-/* xor imm32 to r32 */
-void XOR32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x35 );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 6, to );
- }
- write32( from );
-}
-
-/* xor imm32 to m32 */
-void XOR32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 6, to, 4);
- write32( from );
-}
-
-/* xor r32 to r32 */
-void XOR32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x31 );
- ModRM( 3, from, to );
-}
-
-/* xor r16 to r16 */
-void XOR16RtoR( x86IntRegType to, x86IntRegType from )
-{
- write8( 0x66 );
- RexRB(0,from,to);
- write8( 0x31 );
- ModRM( 3, from, to );
-}
-
-/* xor r32 to m32 */
-void XOR32RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x31), true, from, to, 0);
-}
-
-/* xor m32 to r32 */
-void XOR32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x33), true, to, from, 0);
-}
-
-// xor imm16 to r16
-void XOR16ItoR( x86IntRegType to, u16 from )
-{
- write8(0x66);
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x35 );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 6, to );
- }
- write16( from );
-}
-
-// xor r16 to m16
-void XOR16RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x31), true, from, to, 0);
-}
-
-/* and imm32 to r64 */
-void AND64I32toR( x86IntRegType to, u32 from )
-{
- RexB(1, to);
- if ( to == EAX ) {
- write8( 0x25 );
- } else {
- write8( 0x81 );
- ModRM( 3, 0x4, to );
- }
- write32( from );
-}
-
-/* and m64 to r64 */
-void AND64MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP1(0x23), true, to, from, 0);
-}
-
-/* and r64 to m64 */
-void AND64RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(1, VAROP1(0x21), true, from, to, 0);
-}
-
-/* and r64 to r64 */
-void AND64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1, from, to);
- write8( 0x21 );
- ModRM( 3, from, to );
-}
-
-/* and imm32 to m64 */
-void AND64I32toM( uptr to, u32 from )
-{
- MEMADDR_OP(1, VAROP1(0x81), false, 4, to, 4);
- write32( from );
-}
-
-/* and imm32 to r32 */
-void AND32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- 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 )
-{
- RexB(0,to);
- write8( 0x83 );
- ModRM( 3, 0x4, to );
- write8( from );
-}
-
-/* and imm32 to m32 */
-void AND32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 4, to, 4);
- write32(from);
-}
-
-/* and sign ext imm8 to m32 */
-void AND32I8toM( uptr to, u8 from )
-{
- MEMADDR_OP(0, VAROP1(0x83), false, 4, to, 1);
- write8( from );
-}
-
-/* and r32 to r32 */
-void AND32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x21 );
- ModRM( 3, from, to );
-}
-
-/* and r32 to m32 */
-void AND32RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x21), true, from, to, 0);
-}
-
-/* and m32 to r32 */
-void AND32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x23), true, to, from, 0);
-}
-
-// and r16 to r16
-void AND16RtoR( x86IntRegType to, x86IntRegType from )
-{
- write8(0x66);
- RexRB(0,to,from);
- write8( 0x23 );
- ModRM( 3, to, from );
-}
-
-/* and imm16 to r16 */
-void AND16ItoR( x86IntRegType to, u16 from )
-{
- write8(0x66);
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x25 );
- } else {
- write8( 0x81 );
- ModRM( 3, 0x4, to );
- }
- write16( from );
-}
-
-/* and imm16 to m16 */
-void AND16ItoM( uptr to, u16 from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 4, to, 2);
- write16( from );
-}
-
-/* and r16 to m16 */
-void AND16RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x21), true, from, to, 0);
-}
-
-/* and m16 to r16 */
-void AND16MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x23), true, to, from, 0);
-}
-
-/* and imm8 to r8 */
-void AND8ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x24 );
- } else {
- write8( 0x80 );
- ModRM( 3, 0x4, to );
- }
- write8( from );
-}
-
-/* and imm8 to m8 */
-void AND8ItoM( uptr to, u8 from )
-{
- MEMADDR_OP(0, VAROP1(0x80), false, 4, to, 1);
- write8( from );
-}
-
-// and r8 to r8
-void AND8RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,to,from);
- write8( 0x22 );
- ModRM( 3, to, from );
-}
-
-/* and r8 to m8 */
-void AND8RtoM( uptr to, x86IntRegType from )
-{
- MEMADDR_OP(0, VAROP1(0x20), true, from, to, 0);
-}
-
-/* and m8 to r8 */
-void AND8MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x22), true, to, from, 0);
-}
-
-/* not r64 */
-void NOT64R( x86IntRegType from )
-{
- RexB(1, from);
- write8( 0xF7 );
- ModRM( 3, 2, from );
-}
-
-/* not r32 */
-void NOT32R( x86IntRegType from )
-{
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 2, from );
-}
-
-// not m32
-void NOT32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 2, from, 0);
-}
-
-/* neg r64 */
-void NEG64R( x86IntRegType from )
-{
- RexB(1, from);
- write8( 0xF7 );
- ModRM( 3, 3, from );
-}
-
-/* neg r32 */
-void NEG32R( x86IntRegType from )
-{
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 3, from );
-}
-
-void NEG32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 3, from, 0);
-}
-
-/* neg r16 */
-void NEG16R( x86IntRegType from )
-{
- write8( 0x66 );
- RexB(0,from);
- write8( 0xF7 );
- ModRM( 3, 3, from );
-}
-
-////////////////////////////////////
-// jump instructions /
-////////////////////////////////////
-
-u8* JMP( uptr to ) {
- uptr jump = ( x86Ptr - (s8*)to ) - 1;
-
- if ( jump > 0x7f ) {
- assert( to <= 0xffffffff );
- 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( uptr to )
-{
- assert(SPTR32((sptr)to));
- write8( 0xE9 );
- write32( (sptr)to );
- return (u32*)(x86Ptr - 4 );
-}
-
-/* jmp r32/r64 */
-void JMPR( x86IntRegType to )
-{
- RexB(0, to);
- write8( 0xFF );
- ModRM( 3, 4, to );
-}
-
-// jmp m32
-void JMP32M( uptr to )
-{
- /* FIXME */
- MEMADDR_OP(0, VAROP1(0xFF), false, 4, to, 0);
-}
-
-/* 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( uptr func )
-{
- sptr p = MEMADDR_(func, 5);
- if (SPTR32(p))
- {
- CALL32(p);
- }
- else
- {
- MOV64ItoR(X86_TEMP, func);
- CALL64R(X86_TEMP);
- }
-}
-
-/* call rel32 */
-void CALL32( s32 to )
-{
- write8( 0xE8 );
- write32( to );
-}
-
-/* call r32 */
-void CALL32R( x86IntRegType to )
-{
- RexB(0, to);
- write8( 0xFF );
- ModRM( 3, 2, to );
-}
-
-/* call r64 */
-void CALL64R( x86IntRegType to )
-{
- RexB(0, to);
- write8( 0xFF );
- ModRM( 3, 2, to );
-}
-
-////////////////////////////////////
-// misc instructions /
-////////////////////////////////////
-
-/* cmp imm32 to r64 */
-void CMP64I32toR( x86IntRegType to, u32 from )
-{
- RexB(1, to);
- if ( to == EAX ) {
- write8( 0x3D );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 7, to );
- }
- write32( from );
-}
-
-/* cmp m64 to r64 */
-void CMP64MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(1, VAROP1(0x3B), true, 2, from, 0);
-}
-
-// cmp r64 to r64
-void CMP64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1,from,to);
- write8( 0x39 );
- ModRM( 3, from, to );
-}
-
-/* cmp imm32 to r32 */
-void CMP32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- if ( to == EAX ) {
- write8( 0x3D );
- }
- else {
- write8( 0x81 );
- ModRM( 3, 7, to );
- }
- write32( from );
-}
-
-/* cmp imm32 to m32 */
-void CMP32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0x81), false, 7, to, 4);
- write32(from);
-}
-
-/* cmp r32 to r32 */
-void CMP32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x39 );
- ModRM( 3, from, to );
-}
-
-/* cmp m32 to r32 */
-void CMP32MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x3B), true, to, from, 0);
-}
-
-// cmp imm8 to [r32]
-void CMP32I8toRm( x86IntRegType to, u8 from)
-{
- RexB(0,to);
- write8( 0x83 );
- ModRM( 0, 7, to );
- write8(from);
-}
-
-// cmp imm32 to [r32+off]
-void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off)
-{
- RexB(0,to);
- write8( 0x83 );
- ModRM( 1, 7, to );
- write8(off);
- write8(from);
-}
-
-// cmp imm8 to [r32]
-void CMP32I8toM( uptr to, u8 from)
-{
- MEMADDR_OP(0, VAROP1(0x83), false, 7, to, 1);
- write8( from );
-}
-
-/* cmp imm16 to r16 */
-void CMP16ItoR( x86IntRegType to, u16 from )
-{
- write8( 0x66 );
- RexB(0,to);
- if ( to == EAX )
- {
- write8( 0x3D );
- }
- else
- {
- write8( 0x81 );
- ModRM( 3, 7, to );
- }
- write16( from );
-}
-
-/* cmp imm16 to m16 */
-void CMP16ItoM( uptr to, u16 from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 7, to, 2);
- write16( from );
-}
-
-/* cmp r16 to r16 */
-void CMP16RtoR( x86IntRegType to, x86IntRegType from )
-{
- write8( 0x66 );
- RexRB(0,from,to);
- write8( 0x39 );
- ModRM( 3, from, to );
-}
-
-/* cmp m16 to r16 */
-void CMP16MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x66, 0x3B), true, to, from, 0);
-}
-
-// cmp imm8 to r8
-void CMP8ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- if ( to == EAX )
- {
- write8( 0x3C );
- }
- else
- {
- write8( 0x80 );
- ModRM( 3, 7, to );
- }
- write8( from );
-}
-
-// cmp m8 to r8
-void CMP8MtoR( x86IntRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP1(0x3A), true, to, from, 0);
-}
-
-/* test r64 to r64 */
-void TEST64RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(1, from, to);
- write8( 0x85 );
- ModRM( 3, from, to );
-}
-
-/* test imm32 to r32 */
-void TEST32ItoR( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- if ( to == EAX )
- {
- write8( 0xA9 );
- }
- else
- {
- write8( 0xF7 );
- ModRM( 3, 0, to );
- }
- write32( from );
-}
-
-void TEST32ItoM( uptr to, u32 from )
-{
- MEMADDR_OP(0, VAROP1(0xF7), false, 0, to, 4);
- write32( from );
-}
-
-/* test r32 to r32 */
-void TEST32RtoR( x86IntRegType to, x86IntRegType from )
-{
- RexRB(0,from,to);
- write8( 0x85 );
- ModRM( 3, from, to );
-}
-
-// test imm32 to [r32]
-void TEST32ItoRm( x86IntRegType to, u32 from )
-{
- RexB(0,to);
- write8( 0xF7 );
- ModRM( 0, 0, to );
- write32(from);
-}
-
-// test imm16 to r16
-void TEST16ItoR( x86IntRegType to, u16 from )
-{
- write8(0x66);
- RexB(0,to);
- if ( to == EAX )
- {
- write8( 0xA9 );
- }
- else
- {
- write8( 0xF7 );
- ModRM( 3, 0, to );
- }
- write16( from );
-}
-
-// test r16 to r16
-void TEST16RtoR( x86IntRegType to, x86IntRegType from )
-{
- write8(0x66);
- RexRB(0,from,to);
- write16( 0x85 );
- ModRM( 3, from, to );
-}
-
-// test imm8 to r8
-void TEST8ItoR( x86IntRegType to, u8 from )
-{
- RexB(0,to);
- if ( to == EAX )
- {
- write8( 0xA8 );
- }
- else
- {
- write8( 0xF6 );
- ModRM( 3, 0, to );
- }
- write8( from );
-}
-
-// test imm8 to r8
-void TEST8ItoM( uptr to, u8 from )
-{
- MEMADDR_OP(0, VAROP1(0xF6), false, 0, to, 1);
- 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 imm32 */
-void PUSH32I( u32 from )
-{
- //X86_64ASSERT(); //becomes sign extended in x86_64
- write8( 0x68 );
- write32( from );
-}
-
-#ifdef __x86_64__
-
-/* push r64 */
-void PUSH64R( x86IntRegType from )
-{
- RexB(0,from);
- //write8( 0x51 | from );
- write8( 0x50 | from );
-}
-
-/* push m64 */
-void PUSH64M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
-}
-
-/* pop r64 */
-void POP64R( x86IntRegType from ) {
- RexB(0,from);
- //write8( 0x59 | from );
- write8( 0x58 | from );
-}
-
-void PUSHR(x86IntRegType from) { PUSH64R(from); }
-void POPR(x86IntRegType from) { POP64R(from); }
-
-#else
-
-/* push r32 */
-void PUSH32R( x86IntRegType from ) { write8( 0x50 | from ); }
-
-/* push m32 */
-void PUSH32M( uptr from )
-{
- MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
-}
-
-/* pop r32 */
-void POP32R( x86IntRegType from ) { write8( 0x58 | from ); }
-
-/* pushad */
-void PUSHA32( void ) { write8( 0x60 ); }
-
-/* popad */
-void POPA32( void ) { write8( 0x61 ); }
-
-void PUSHR(x86IntRegType from) { PUSH32R(from); }
-void POPR(x86IntRegType from) { POP32R(from); }
-
-#endif
-
-
-/* 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); }
-
-#ifdef __x86_64__
-void CDQE( void ) { RexR(1,0); write8( 0x98 ); }
-#endif
-
-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)
-{
- RexRB(0,to,from);
- write8(0x8d);
-
- if( (from&7) == 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)
-{
- RexRXB(0, to, from0, from1);
- write8(0x8d);
-
- if( (from1&7) == EBP ) {
- 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 ) {
- RexRXB(0,to,from,0);
- write8(0x8d);
- ModRM(0, to, 4);
- ModRM(scale, from, 5);
- write32(0);
- }
- else {
- assert( to != ESP );
- MOV32RtoR(to, from);
- LEA32RStoR(to, to, scale);
- }
-}
-
-#endif
-
-#endif
+/* + * ix86 core v0.6.2 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + */ + +#ifdef __x86_64__ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include "ix86-64.h" + +#ifdef __x86_64__ + +#ifdef _MSC_VER +// visual studio calling convention +x86IntRegType g_x86savedregs[] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15 }; +x86IntRegType g_x86tempregs[] = { R8, R9, R10, R11, RDX, RCX }; + +// arranged in savedreg -> tempreg order +x86IntRegType g_x86allregs[14] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15, R8, R9, R10, R11, RDX, RCX }; + +#else +// standard calling convention + +// registers saved by called functions (no need to flush them across calls) +x86IntRegType g_x86savedregs[] = { RBX, RBP, R12, R13, R14, R15 }; +// temp registers that need to be saved across calls +x86IntRegType g_x86tempregs[] = { RCX, RDX, R8, R9, R10, R11, RSI, RDI }; + +// arranged in savedreg -> tempreg order +x86IntRegType g_x86allregs[14] = { RBX, RBP, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11, RSI, RDI }; + +#endif + +x86IntRegType g_x868bitregs[11] = { RBX, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11 }; +x86IntRegType g_x86non8bitregs[3] = { RBP, RSI, RDI }; + +#endif // __x86_64__ + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +void WriteRmOffset(x86IntRegType to, int offset) +{ + if( (to&7) == ESP ) { + if( offset == 0 ) { + ModRM( 0, 0, 4 ); + ModRM( 0, ESP, 4 ); + } + else if( offset < 128 && 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 && offset >= -128 ) { + ModRM( 1, 0, to ); + write8(offset); + } + else { + ModRM( 2, 0, to ); + write32(offset); + } + } +} + +void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset) +{ + if ((from&7) == ESP) { + if( offset == 0 ) { + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + else if( offset < 128 && offset >= -128 ) { + ModRM( 1, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write8(offset); + } + else { + ModRM( 2, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 && offset >= -128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } + } +} + +// This function is just for rec debugging purposes +void CheckX86Ptr( void ) +{ +} + +void writeVAROP(unsigned opl, u64 op) +{ + while (opl--) + { + write8(op & 0xFF); + op >>= 8; + } +} + +#define writeVARROP(REX, opl, op) ({ \ + if (opl > 1 && ((op & 0xFF) == 0x66 || (op & 0xFF) == 0xF3 || (op & 0xFF) == 0xF2)) { \ + write8(op & 0xFF); \ + opl --; \ + op >>= 8; \ + } \ + REX; \ + writeVAROP(opl, op); \ + }) + +void MEMADDR_OP(bool w, unsigned opl, u64 op, bool isreg, int reg, uptr p, sptr off) +{ +#ifdef __x86_64__ + sptr pr = MEMADDR_(p, 5 + opl + (w || reg >= 8) + off); + if (SPTR32(pr)) + { + writeVARROP(RexR(w, reg), opl, op); + ModRM(0, reg, DISP32); + write32(pr); + } + else if (UPTR32(p)) + { + writeVARROP(RexR(w, reg), opl, op); + ModRM(0, reg, SIB); + SibSB(0, SIB, DISP32); + write32(p); + } + else + { + assert(!isreg || reg != X86_TEMP); + MOV64ItoR(X86_TEMP, p); + writeVARROP(RexRB(w, reg, X86_TEMP), opl, op); + ModRM(0, reg, X86_TEMP); + } +#else + writeVARROP(RexR(w, reg), opl, op); + ModRM(0, reg, DISP32); + write32(p); +#endif +} + +void SET8R( int cc, int to ) +{ + RexB(0, 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 ) +{ + RexRB(0,to, from); + write8( 0x0F ); + write8( cc ); + ModRM( 3, to, from ); +} + +void CMOV32MtoR( int cc, x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, cc), true, to, from, 0); +} + +//////////////////////////////////////////////////// +void x86SetPtr( char* ptr ) +{ + x86Ptr = ptr; +} + +//////////////////////////////////////////////////// +void x86Shutdown( void ) +{ +} + +//////////////////////////////////////////////////// +void x86SetJ8( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + SysPrintf( "j8 greater than 0x7f!!\n" ); + assert(0); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + SysPrintf( "j8 greater than 0x7f!!\n" ); + //assert(0); + } + + if( ((uptr)x86Ptr&0xf) > 4 ) { + + uptr newjump = jump + 16-((uptr)x86Ptr&0xf); + + if( newjump <= 0x7f ) { + jump = newjump; + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + } + *j8 = (u8)jump; +} + +void x86SetJ16( u16 *j16 ) +{ + // doesn't work + u32 jump = ( x86Ptr - (s8*)j16 ) - 2; + + if ( jump > 0x7fff ) { + SysPrintf( "j16 greater than 0x7fff!!\n" ); + //assert(0); + } + *j16 = (u16)jump; +} + +void x86SetJ16A( u16 *j16 ) +{ + if( ((uptr)x86Ptr&0xf) > 4 ) { + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + x86SetJ16(j16); +} + +//////////////////////////////////////////////////// +void x86SetJ32( u32* j32 ) +{ + *j32 = ( x86Ptr - (s8*)j32 ) - 4; +} + +void x86SetJ32A( u32* j32 ) +{ + while((uptr)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 ) +{ + RexRB(1, from, to); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r64 to m64 */ +void MOV64RtoM( uptr to, x86IntRegType from ) +{ + if (from == RAX) + { + RexR(1, 0); + write8(0xA3); + write64(to); + } + else + { + MEMADDR_OP(1, VAROP1(0x89), true, from, to, 0); + } +} + +/* mov m64 to r64 */ +void MOV64MtoR( x86IntRegType to, uptr from ) +{ + if (to == RAX) + { + RexR(1, 0); + write8(0xA1); + write64(from); + } + else + { + MEMADDR_OP(1, VAROP1(0x8B), true, to, from, 0); + } +} + +/* mov imm32 to m64 */ +void MOV64I32toM(uptr to, u32 from ) +{ + MEMADDR_OP(1, VAROP1(0xC7), false, 0, to, 4); + write32(from); +} + +// mov imm64 to r64 +void MOV64ItoR( x86IntRegType to, u64 from) +{ + RexB(1, to); + write8( 0xB8 | (to & 0x7) ); + write64( from ); +} + +/* mov imm32 to r64 */ +void MOV64I32toR( x86IntRegType to, s32 from ) +{ + RexB(1, to); + write8( 0xC7 ); + ModRM( 0, 0, to ); + write32( from ); +} + +// mov imm64 to [r64+off] +void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset) +{ + RexB(1,to); + write8( 0xC7 ); + WriteRmOffset(to, offset); + write32(from); +} + +// mov [r64+offset] to r64 +void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(1, to, from); + write8( 0x8B ); + WriteRmOffsetFrom(to, from, offset); +} + +/* mov [r64][r64*scale] to r64 */ +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + RexRXB(1, to, from2, from); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov r64 to [r64+offset] */ +void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(1,from,to); + write8( 0x89 ); + WriteRmOffsetFrom(from, to, offset); +} + +/* mov r64 to [r64][r64*scale] */ +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + RexRXB(1, to, from2, from); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + + +/* mov r32 to r32 */ +void MOV32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, from, to); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r32 to m32 */ +void MOV32RtoM( uptr to, x86IntRegType from ) +{ + if (from == EAX) + { + write8(0xA3); + write64(to); + } + else + { + MEMADDR_OP(0, VAROP1(0x89), true, from, to, 0); + } +} + +/* mov m32 to r32 */ +void MOV32MtoR( x86IntRegType to, uptr from ) +{ + if (to == RAX) + { + write8(0xA1); + write64(from); + } + else + { + MEMADDR_OP(0, VAROP1(0x8B), true, to, from, 0); + } +} + +/* mov [r32] to r32 */ +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) { + RexRB(0, to, from); + write8(0x8B); + WriteRmOffsetFrom(to, from, 0); +} + +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) { + RexRB(0, to, from); + write8( 0x8B ); + WriteRmOffsetFrom(to, from, offset); +} + +/* mov [r32+r32*scale] to r32 */ +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + RexRXB(0,to,from2,from); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +// mov r32 to [r32<<scale+from2] +void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, int from2, int scale ) +{ + RexRXB(0,to,from1,0); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +/* mov r32 to [r32] */ +void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) { + RexRB(0, from, to); + if ((to&7) == 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) { + RexRXB(0, to, from2, from); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov imm32 to r32 */ +void MOV32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0, to); + write8( 0xB8 | (to & 0x7) ); + write32( from ); +} + +/* mov imm32 to m32 */ +void MOV32ItoM(uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0xC7), false, 0, to, 4); + write32(from); +} + +// mov imm32 to [r32+off] +void MOV32ItoRmOffset( x86IntRegType to, u32 from, int offset) +{ + RexB(0,to); + write8( 0xC7 ); + WriteRmOffset(to, offset); + write32(from); +} + +// mov r32 to [r32+off] +void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset) +{ + RexRB(0,from,to); + write8( 0x89 ); + WriteRmOffsetFrom(from, to, offset); +} + +/* mov r16 to m16 */ +void MOV16RtoM(uptr to, x86IntRegType from ) +{ + if (from == EAX) + { + write8(0x66); + write8(0xA3); + write64(to); + } + else + { + MEMADDR_OP(0, VAROP2(0x66, 0x89), true, from, to, 0); + } +} + +/* mov m16 to r16 */ +void MOV16MtoR( x86IntRegType to, uptr from ) +{ + if (to == EAX) + { + write8(0x66); + write8(0xA1); + write64(from); + } + else + { + MEMADDR_OP(0, VAROP2(0x66, 0x8B), true, to, from, 0); + } +} + +void MOV16RmtoR( x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + RexRB(0,to,from); + write8( 0x8B ); + WriteRmOffsetFrom(to, from, 0); +} + +void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + write8( 0x66 ); + RexRB(0,to,from); + write8( 0x8B ); + WriteRmOffsetFrom(to, from, offset); +} + +void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write8(0x66); + RexRXB(0,to,from1,0); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +void MOV16RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + RexRB(0,from,to); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov imm16 to m16 */ +void MOV16ItoM( uptr to, u16 from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0xC7), false, 0, to, 2); + write16( from ); +} + +/* mov r16 to [r32][r32*scale] */ +void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x66 ); + RexRXB(0,to,from2,from); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV16ItoR( x86IntRegType to, u16 from ) +{ + RexB(0, to); + write16( 0xB866 | ((to & 0x7)<<8) ); + write16( from ); +} + +// mov imm16 to [r16+off] +void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset) +{ + write8(0x66); + RexB(0,to); + write8( 0xC7 ); + WriteRmOffset(to, offset); + write16(from); +} + +// mov r16 to [r16+off] +void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset) +{ + write8(0x66); + RexRB(0,from,to); + write8( 0x89 ); + WriteRmOffsetFrom(from, to, offset); +} + +/* mov r8 to m8 */ +void MOV8RtoM( uptr to, x86IntRegType from ) +{ + if (from == EAX) + { + write8(0xA2); + write64(to); + } + else + { + MEMADDR_OP(0, VAROP1(0x88), true, from, to, 0); + } +} + +/* mov m8 to r8 */ +void MOV8MtoR( x86IntRegType to, uptr from ) +{ + if (to == EAX) + { + write8(0xA0); + write64(from); + } + else + { + MEMADDR_OP(0, VAROP1(0x8A), true, to, from, 0); + } +} + +/* mov [r32] to r8 */ +void MOV8RmtoR(x86IntRegType to, x86IntRegType from) +{ + RexRB(0,to,from); + write8( 0x8A ); + WriteRmOffsetFrom(to, from, 0); +} + +void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset) +{ + RexRB(0,to,from); + write8( 0x8A ); + WriteRmOffsetFrom(to, from, offset); +} + +void MOV8RtoRm(x86IntRegType to, x86IntRegType from) +{ + RexRB(0,from,to); + write8( 0x88 ); + WriteRmOffsetFrom(from, to, 0); +} + +/* mov imm8 to m8 */ +void MOV8ItoM( uptr to, u8 from ) +{ + MEMADDR_OP(0, VAROP1(0xC6), false, 0, to, 1); + write8( from ); +} + +// mov imm8 to r8 +void MOV8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0, to); + write8( 0xB0 | (to & 0x7) ); + write8( from ); +} + +// mov imm8 to [r8+off] +void MOV8ItoRmOffset( x86IntRegType to, u8 from, int offset) +{ + assert( to != ESP ); + RexB(0,to); + write8( 0xC6 ); + WriteRmOffset(to,offset); + write8(from); +} + +// mov r8 to [r8+off] +void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset) +{ + assert( to != ESP ); + RexRB(0,from,to); + write8( 0x88 ); + WriteRmOffsetFrom(from,to,offset); +} + +/* movsx r8 to r32 */ +void MOVSX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xBE0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xBE0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(0,to,from); + write16( 0xBE0F ); + WriteRmOffsetFrom(to,from,offset); +} + +/* movsx m8 to r32 */ +void MOVSX32M8toR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xBE), true, to, from, 0); +} + +/* movsx r16 to r32 */ +void MOVSX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xBF0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xBF0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(0,to,from); + write16( 0xBF0F ); + WriteRmOffsetFrom(to,from,offset); +} + +/* movsx m16 to r32 */ +void MOVSX32M16toR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xBF), true, to, from, 0); +} + +/* movzx r8 to r32 */ +void MOVZX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xB60F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xB60F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(0,to,from); + write16( 0xB60F ); + WriteRmOffsetFrom(to,from,offset); +} + +/* movzx m8 to r32 */ +void MOVZX32M8toR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xB6), true, to, from, 0); +} + +/* movzx r16 to r32 */ +void MOVZX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xB70F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xB70F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(0,to,from); + write16( 0xB70F ); + WriteRmOffsetFrom(to,from,offset); +} + +/* movzx m16 to r32 */ +void MOVZX32M16toR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xB7), true, to, from, 0); +} + +#ifdef __x86_64__ + +/* movzx r8 to r64 */ +void MOVZX64R8toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1,to,from); + write16( 0xB60F ); + ModRM( 3, to, from ); +} + +void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1,to,from); + write16( 0xB60F ); + ModRM( 0, to, from ); +} + +void MOVZX64Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(1,to,from); + write16( 0xB60F ); + WriteRmOffsetFrom(to,from,offset); +} + +/* movzx m8 to r64 */ +void MOVZX64M8toR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP2(0x0F, 0xB6), true, to, from, 0); +} + +/* movzx r16 to r64 */ +void MOVZX64R16toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1,to,from); + write16( 0xB70F ); + ModRM( 3, to, from ); +} + +void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1,to,from); + write16( 0xB70F ); + ModRM( 0, to, from ); +} + +void MOVZX64Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(1,to,from); + write16( 0xB70F ); + WriteRmOffsetFrom(to,from,offset); +} + +/* movzx m16 to r64 */ +void MOVZX64M16toR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP2(0x0F, 0xB7), true, to, from, 0); +} +#endif + +/* cmovbe r32 to r32 */ +void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x46, to, from ); +} + +/* cmovbe m32 to r32*/ +void CMOVBE32MtoR( x86IntRegType to, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from ) +{ + CMOV32MtoR( 0x4E, to, from ); +} + +//////////////////////////////////// +// arithmetic instructions / +//////////////////////////////////// + +/* add imm32 to r64 */ +void ADD64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if (from <= 0x7f) + { + write8(0x83); + ModRM( 3, 0, to ); + write8(from); + } + else + { + if (to == RAX) { + write8( 0x05 ); + } else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); + } +} + +/* add m64 to r64 */ +void ADD64MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP1(0x03), true, to, from, 0); +} + +/* add r64 to r64 */ +void ADD64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add imm32 to r32 */ +void ADD32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0, to); + if ( to == EAX) { + write8( 0x05 ); + } + else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add imm32 to m32 */ +void ADD32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 0, to, 4); + write32(from); +} + +// add imm32 to [r32+off] +void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset) +{ + RexB(0,to); + write8( 0x81 ); + WriteRmOffset(to,offset); + write32(from); +} + +/* add r32 to r32 */ +void ADD32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, from, to); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add r32 to m32 */ +void ADD32RtoM(uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x01), true, from, to, 0); +} + +/* add m32 to r32 */ +void ADD32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x03), true, to, from, 0); +} + +// add r16 to r16 +void ADD16RtoR( x86IntRegType to , x86IntRegType from ) +{ + write8(0x66); + RexRB(0,to,from); + write8( 0x03 ); + ModRM( 3, to, from ); +} + +/* add imm16 to r16 */ +void ADD16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + RexB(0,to); + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +/* add imm16 to m16 */ +void ADD16ItoM( uptr to, u16 from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 0, to, 2); + write16( from ); +} + +/* add r16 to m16 */ +void ADD16RtoM(uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x01), true, from, to, 0); +} + +/* add m16 to r16 */ +void ADD16MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x03), true, to, from, 0); +} + +// add m8 to r8 +void ADD8MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x02), true, to, from, 0); +} + +/* adc imm32 to r32 */ +void ADC32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x15 ); + } + else { + write8( 0x81 ); + ModRM( 3, 2, to ); + } + write32( from ); +} + +/* adc imm32 to m32 */ +void ADC32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 2, to, 4); + write32(from); +} + +/* adc r32 to r32 */ +void ADC32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x11 ); + ModRM( 3, from, to ); +} + +/* adc m32 to r32 */ +void ADC32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x13), true, to, from, 0); +} + +// adc r32 to m32 +void ADC32RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x11), true, from, to, 0); +} + + +#ifdef __x86_64__ +void INC32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM(3,0,to); +} +#else +/* inc r32 */ +void INC32R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x40 + to ); +} +#endif +/* inc m32 */ +void INC32M( uptr to ) +{ + MEMADDR_OP(0, VAROP1(0xFF), false, 0, to, 0); +} + +/* inc r16 */ +void INC16R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x66 ); + write8( 0x40 + to ); +} + +/* inc m16 */ +void INC16M( uptr to ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 0, to, 0); +} + + +/* sub imm32 to r64 */ +void SUB64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if (from <= 0x7f) + { + write8(0x83); + ModRM( 3, 5, to ); + write8(from); + } + else + { + if ( to == RAX ) { + write8( 0x2D ); + } + else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); + } +} + +/* sub r64 to r64 */ +void SUB64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m64 to r64 */ +void SUB64MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP1(0x2B), true, to, from, 0); +} + +/* sub imm32 to r32 */ +void SUB32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x2D ); + } + else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub imm32 to m32 */ +void SUB32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 5, to, 4); + write32(from); +} + +/* sub r32 to r32 */ +void SUB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, from, to); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m32 to r32 */ +void SUB32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x2B), true, to, from, 0); +} + +// sub r32 to m32 +void SUB32RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x29), true, from, to, 0); +} + +// sub r16 to r16 +void SUB16RtoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexRB(0,to,from); + write8( 0x2b ); + ModRM( 3, to, from ); +} + +/* sub imm16 to r16 */ +void SUB16ItoR( x86IntRegType to, u16 from ) { + write8( 0x66 ); + RexB(0,to); + if ( to == EAX ) { + write8( 0x2D ); + } else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write16( from ); +} + +/* sub imm16 to m16 */ +void SUB16ItoM( uptr to, u16 from ) { + MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 5, to, 2); + write16( from ); +} + +/* sub m16 to r16 */ +void SUB16MtoR( x86IntRegType to, uptr from ) { + MEMADDR_OP(0, VAROP2(0x66, 0x2B), true, to, from, 0); +} + +/* sbb r64 to r64 */ +void SBB64RtoR( x86IntRegType to, x86IntRegType from ) { + RexRB(1, from,to); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb imm32 to r32 */ +void SBB32ItoR( x86IntRegType to, u32 from ) { + RexB(0,to); + if ( to == EAX ) { + write8( 0x1D ); + } else { + write8( 0x81 ); + ModRM( 3, 3, to ); + } + write32( from ); +} + +/* sbb imm32 to m32 */ +void SBB32ItoM( uptr to, u32 from ) { + MEMADDR_OP(0, VAROP1(0x81), false, 3, to, 4); + write32( from ); +} + +/* sbb r32 to r32 */ +void SBB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb m32 to r32 */ +void SBB32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x1B), true, to, from, 0); +} + +/* sbb r32 to m32 */ +void SBB32RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x19), true, from, to, 0); +} + +#ifdef __x86_64__ +void DEC32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM(3,1,to); +} +#else +/* dec r32 */ +void DEC32R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x48 + to ); +} +#endif + +/* dec m32 */ +void DEC32M( uptr to ) +{ + MEMADDR_OP(0, VAROP1(0xFF), false, 1, to, 0); +} + +/* dec r16 */ +void DEC16R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x66 ); + write8( 0x48 + to ); +} + +/* dec m16 */ +void DEC16M( uptr to ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 1, to, 0); +} + +/* mul eax by r32 to edx:eax */ +void MUL32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 4, from ); +} + +/* imul eax by r32 to edx:eax */ +void IMUL32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 5, from ); +} + +/* mul eax by m32 to edx:eax */ +void MUL32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 4, from, 0); +} + +/* imul eax by m32 to edx:eax */ +void IMUL32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 5, from, 0); +} + +/* imul r32 by r32 to r32 */ +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xAF0F ); + ModRM( 3, to, from ); +} + +/* div eax by r32 to edx:eax */ +void DIV32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 6, from ); +} + +/* idiv eax by r32 to edx:eax */ +void IDIV32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 7, from ); +} + +/* div eax by m32 to edx:eax */ +void DIV32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 6, from, 0); +} + +/* idiv eax by m32 to edx:eax */ +void IDIV32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 7, from, 0); +} + +//////////////////////////////////// +// shifting instructions / +//////////////////////////////////// + +/* shl imm8 to r64 */ +void SHL64ItoR( x86IntRegType to, u8 from ) +{ + RexB(1, to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 4, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl cl to r64 */ +void SHL64CLtoR( x86IntRegType to ) +{ + RexB(1, to); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +/* shr imm8 to r64 */ +void SHR64ItoR( x86IntRegType to, u8 from ) +{ + RexB(1,to); + if ( from == 1 ) { + write8( 0xD1 ); + ModRM( 3, 5, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); +} + +/* shr cl to r64 */ +void SHR64CLtoR( x86IntRegType to ) +{ + RexB(1, to); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +/* shl imm8 to r32 */ +void SHL32ItoR( x86IntRegType to, u8 from ) +{ + RexB(0, to); + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl imm8 to m32 */ +void SHL32ItoM( uptr to, u8 from ) +{ + if ( from == 1 ) + { + MEMADDR_OP(0, VAROP1(0xD1), false, 4, to, 0); + } + else + { + MEMADDR_OP(0, VAROP1(0xC1), false, 4, to, 1); + write8( from ); + } +} + +/* shl cl to r32 */ +void SHL32CLtoR( x86IntRegType to ) +{ + RexB(0,to); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +// shl imm8 to r16 +void SHL16ItoR( x86IntRegType to, u8 from ) +{ + write8(0x66); + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +// shl imm8 to r8 +void SHL8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + 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 ) { + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* shr imm8 to m32 */ +void SHR32ItoM( uptr to, u8 from ) +{ + if ( from == 1 ) + { + MEMADDR_OP(0, VAROP1(0xD1), false, 5, to, 0); + } + else + { + MEMADDR_OP(0, VAROP1(0xC1), false, 5, to, 1); + write8( from ); + } +} + +/* shr cl to r32 */ +void SHR32CLtoR( x86IntRegType to ) +{ + RexB(0,to); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +// shr imm8 to r8 +void SHR8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + 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 ) +{ + RexB(1,to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar cl to r64 */ +void SAR64CLtoR( x86IntRegType to ) +{ + RexB(1, to); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +/* sar imm8 to r32 */ +void SAR32ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar imm8 to m32 */ +void SAR32ItoM( uptr to, u8 from ) +{ + if (from == 1) + { + MEMADDR_OP(0, VAROP1(0xD1), false, 7, to, 0); + } + else + { + MEMADDR_OP(0, VAROP1(0xC1), false, 7, to, 1); + write8( from ); + } +} + +/* sar cl to r32 */ +void SAR32CLtoR( x86IntRegType to ) +{ + RexB(0,to); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +// sar imm8 to r16 +void SAR16ItoR( x86IntRegType to, u8 from ) +{ + write8(0x66); + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +void ROR32ItoR( x86IntRegType to,u8 from ) +{ + RexB(0,to); + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xc8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xc8 | to ); + write8( from ); + } +} + +void RCR32ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xd8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xd8 | to ); + write8( from ); + } +} + +// shld imm8 to r32 +void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) +{ + RexRB(0,from,to); + write8( 0x0F ); + write8( 0xA4 ); + ModRM( 3, from, to ); + write8( shift ); +} + +// shrd imm8 to r32 +void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) +{ + RexRB(0,from,to); + write8( 0x0F ); + write8( 0xAC ); + ModRM( 3, from, to ); + write8( shift ); +} + +//////////////////////////////////// +// logical instructions / +//////////////////////////////////// + +/* or imm32 to r32 */ +void OR64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x0D ); + } else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or m64 to r64 */ +void OR64MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP1(0x0B), true, to, from, 0); +} + +/* or r64 to r64 */ +void OR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x09 ); + ModRM( 3, from, to ); +} + +// or r32 to m64 +void OR64RtoM(uptr to, x86IntRegType from ) +{ + MEMADDR_OP(1, VAROP1(0x09), true, from, to, 0); +} + +/* or imm32 to r32 */ +void OR32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or imm32 to m32 */ +void OR32ItoM(uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 1, to, 4); + write32(from); +} + +/* or r32 to r32 */ +void OR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x09 ); + ModRM( 3, from, to ); +} + +/* or r32 to m32 */ +void OR32RtoM(uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x09), true, from, to, 0); +} + +/* or m32 to r32 */ +void OR32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x0B), true, to, from, 0); +} + +// or r16 to r16 +void OR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0,from,to); + write8( 0x09 ); + ModRM( 3, from, to ); +} + +// or imm16 to r16 +void OR16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write16( from ); +} + +// or imm16 to m316 +void OR16ItoM( uptr to, u16 from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 1, to, 2); + write16( from ); +} + +/* or m16 to r16 */ +void OR16MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x0B), true, to, from, 0); +} + +// or r16 to m16 +void OR16RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x09), true, from, to, 0); +} + +// or r8 to r8 +void OR8RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x08 ); + ModRM( 3, from, to ); +} + +// or r8 to m8 +void OR8RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x08), true, from, to, 0); +} + +// or imm8 to m8 +void OR8ItoM( uptr to, u8 from ) +{ + MEMADDR_OP(0, VAROP1(0x80), false, 1, to, 1); + write8( from ); +} + +// or m8 to r8 +void OR8MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x0A), true, to, from, 0); +} + +/* xor imm32 to r64 */ +void XOR64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1,to); + if ( to == EAX ) { + write8( 0x35 ); + } else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor r64 to r64 */ +void XOR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor m64 to r64 */ +void XOR64MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP1(0x33), true, to, from, 0); +} + +/* xor r64 to m64 */ +void XOR64RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(1, VAROP1(0x31), true, from, to, 0); +} + +/* xor imm32 to r32 */ +void XOR32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor imm32 to m32 */ +void XOR32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 6, to, 4); + write32( from ); +} + +/* xor r32 to r32 */ +void XOR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r16 to r16 */ +void XOR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + RexRB(0,from,to); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r32 to m32 */ +void XOR32RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x31), true, from, to, 0); +} + +/* xor m32 to r32 */ +void XOR32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x33), true, to, from, 0); +} + +// xor imm16 to r16 +void XOR16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write16( from ); +} + +// xor r16 to m16 +void XOR16RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x31), true, from, to, 0); +} + +/* and imm32 to r64 */ +void AND64I32toR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and m64 to r64 */ +void AND64MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP1(0x23), true, to, from, 0); +} + +/* and r64 to m64 */ +void AND64RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(1, VAROP1(0x21), true, from, to, 0); +} + +/* and r64 to r64 */ +void AND64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and imm32 to m64 */ +void AND64I32toM( uptr to, u32 from ) +{ + MEMADDR_OP(1, VAROP1(0x81), false, 4, to, 4); + write32( from ); +} + +/* and imm32 to r32 */ +void AND32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + 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 ) +{ + RexB(0,to); + write8( 0x83 ); + ModRM( 3, 0x4, to ); + write8( from ); +} + +/* and imm32 to m32 */ +void AND32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 4, to, 4); + write32(from); +} + +/* and sign ext imm8 to m32 */ +void AND32I8toM( uptr to, u8 from ) +{ + MEMADDR_OP(0, VAROP1(0x83), false, 4, to, 1); + write8( from ); +} + +/* and r32 to r32 */ +void AND32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and r32 to m32 */ +void AND32RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x21), true, from, to, 0); +} + +/* and m32 to r32 */ +void AND32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x23), true, to, from, 0); +} + +// and r16 to r16 +void AND16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0,to,from); + write8( 0x23 ); + ModRM( 3, to, from ); +} + +/* and imm16 to r16 */ +void AND16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write16( from ); +} + +/* and imm16 to m16 */ +void AND16ItoM( uptr to, u16 from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 4, to, 2); + write16( from ); +} + +/* and r16 to m16 */ +void AND16RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x21), true, from, to, 0); +} + +/* and m16 to r16 */ +void AND16MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x23), true, to, from, 0); +} + +/* and imm8 to r8 */ +void AND8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x24 ); + } else { + write8( 0x80 ); + ModRM( 3, 0x4, to ); + } + write8( from ); +} + +/* and imm8 to m8 */ +void AND8ItoM( uptr to, u8 from ) +{ + MEMADDR_OP(0, VAROP1(0x80), false, 4, to, 1); + write8( from ); +} + +// and r8 to r8 +void AND8RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write8( 0x22 ); + ModRM( 3, to, from ); +} + +/* and r8 to m8 */ +void AND8RtoM( uptr to, x86IntRegType from ) +{ + MEMADDR_OP(0, VAROP1(0x20), true, from, to, 0); +} + +/* and m8 to r8 */ +void AND8MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x22), true, to, from, 0); +} + +/* not r64 */ +void NOT64R( x86IntRegType from ) +{ + RexB(1, from); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +/* not r32 */ +void NOT32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +// not m32 +void NOT32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 2, from, 0); +} + +/* neg r64 */ +void NEG64R( x86IntRegType from ) +{ + RexB(1, from); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +/* neg r32 */ +void NEG32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +void NEG32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 3, from, 0); +} + +/* neg r16 */ +void NEG16R( x86IntRegType from ) +{ + write8( 0x66 ); + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +u8* JMP( uptr to ) { + uptr jump = ( x86Ptr - (s8*)to ) - 1; + + if ( jump > 0x7f ) { + assert( to <= 0xffffffff ); + 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( uptr to ) +{ + assert(SPTR32((sptr)to)); + write8( 0xE9 ); + write32( (sptr)to ); + return (u32*)(x86Ptr - 4 ); +} + +/* jmp r32/r64 */ +void JMPR( x86IntRegType to ) +{ + RexB(0, to); + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +// jmp m32 +void JMP32M( uptr to ) +{ + /* FIXME */ + MEMADDR_OP(0, VAROP1(0xFF), false, 4, to, 0); +} + +/* 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( uptr func ) +{ + sptr p = MEMADDR_(func, 5); + if (SPTR32(p)) + { + CALL32(p); + } + else + { + MOV64ItoR(X86_TEMP, func); + CALL64R(X86_TEMP); + } +} + +/* call rel32 */ +void CALL32( s32 to ) +{ + write8( 0xE8 ); + write32( to ); +} + +/* call r32 */ +void CALL32R( x86IntRegType to ) +{ + RexB(0, to); + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call r64 */ +void CALL64R( x86IntRegType to ) +{ + RexB(0, to); + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +//////////////////////////////////// +// misc instructions / +//////////////////////////////////// + +/* cmp imm32 to r64 */ +void CMP64I32toR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x3D ); + } + else { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp m64 to r64 */ +void CMP64MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(1, VAROP1(0x3B), true, 2, from, 0); +} + +// cmp r64 to r64 +void CMP64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1,from,to); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp imm32 to r32 */ +void CMP32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x3D ); + } + else { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp imm32 to m32 */ +void CMP32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0x81), false, 7, to, 4); + write32(from); +} + +/* cmp r32 to r32 */ +void CMP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m32 to r32 */ +void CMP32MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x3B), true, to, from, 0); +} + +// cmp imm8 to [r32] +void CMP32I8toRm( x86IntRegType to, u8 from) +{ + RexB(0,to); + write8( 0x83 ); + ModRM( 0, 7, to ); + write8(from); +} + +// cmp imm32 to [r32+off] +void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off) +{ + RexB(0,to); + write8( 0x83 ); + ModRM( 1, 7, to ); + write8(off); + write8(from); +} + +// cmp imm8 to [r32] +void CMP32I8toM( uptr to, u8 from) +{ + MEMADDR_OP(0, VAROP1(0x83), false, 7, to, 1); + write8( from ); +} + +/* cmp imm16 to r16 */ +void CMP16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + RexB(0,to); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write16( from ); +} + +/* cmp imm16 to m16 */ +void CMP16ItoM( uptr to, u16 from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 7, to, 2); + write16( from ); +} + +/* cmp r16 to r16 */ +void CMP16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + RexRB(0,from,to); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m16 to r16 */ +void CMP16MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x66, 0x3B), true, to, from, 0); +} + +// cmp imm8 to r8 +void CMP8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( to == EAX ) + { + write8( 0x3C ); + } + else + { + write8( 0x80 ); + ModRM( 3, 7, to ); + } + write8( from ); +} + +// cmp m8 to r8 +void CMP8MtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP1(0x3A), true, to, from, 0); +} + +/* test r64 to r64 */ +void TEST64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x85 ); + ModRM( 3, from, to ); +} + +/* test imm32 to r32 */ +void TEST32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +void TEST32ItoM( uptr to, u32 from ) +{ + MEMADDR_OP(0, VAROP1(0xF7), false, 0, to, 4); + write32( from ); +} + +/* test r32 to r32 */ +void TEST32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm32 to [r32] +void TEST32ItoRm( x86IntRegType to, u32 from ) +{ + RexB(0,to); + write8( 0xF7 ); + ModRM( 0, 0, to ); + write32(from); +} + +// test imm16 to r16 +void TEST16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +// test r16 to r16 +void TEST16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0,from,to); + write16( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm8 to r8 +void TEST8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( to == EAX ) + { + write8( 0xA8 ); + } + else + { + write8( 0xF6 ); + ModRM( 3, 0, to ); + } + write8( from ); +} + +// test imm8 to r8 +void TEST8ItoM( uptr to, u8 from ) +{ + MEMADDR_OP(0, VAROP1(0xF6), false, 0, to, 1); + 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 imm32 */ +void PUSH32I( u32 from ) +{ + //X86_64ASSERT(); //becomes sign extended in x86_64 + write8( 0x68 ); + write32( from ); +} + +#ifdef __x86_64__ + +/* push r64 */ +void PUSH64R( x86IntRegType from ) +{ + RexB(0,from); + //write8( 0x51 | from ); + write8( 0x50 | from ); +} + +/* push m64 */ +void PUSH64M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0); +} + +/* pop r64 */ +void POP64R( x86IntRegType from ) { + RexB(0,from); + //write8( 0x59 | from ); + write8( 0x58 | from ); +} + +void PUSHR(x86IntRegType from) { PUSH64R(from); } +void POPR(x86IntRegType from) { POP64R(from); } + +#else + +/* push r32 */ +void PUSH32R( x86IntRegType from ) { write8( 0x50 | from ); } + +/* push m32 */ +void PUSH32M( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0); +} + +/* pop r32 */ +void POP32R( x86IntRegType from ) { write8( 0x58 | from ); } + +/* pushad */ +void PUSHA32( void ) { write8( 0x60 ); } + +/* popad */ +void POPA32( void ) { write8( 0x61 ); } + +void PUSHR(x86IntRegType from) { PUSH32R(from); } +void POPR(x86IntRegType from) { POP32R(from); } + +#endif + + +/* 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); } + +#ifdef __x86_64__ +void CDQE( void ) { RexR(1,0); write8( 0x98 ); } +#endif + +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) +{ + RexRB(0,to,from); + write8(0x8d); + + if( (from&7) == 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) +{ + RexRXB(0, to, from0, from1); + write8(0x8d); + + if( (from1&7) == EBP ) { + 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 ) { + RexRXB(0,to,from,0); + write8(0x8d); + ModRM(0, to, 4); + ModRM(scale, from, 5); + write32(0); + } + else { + assert( to != ESP ); + MOV32RtoR(to, from); + LEA32RStoR(to, to, scale); + } +} + +#endif + +#endif diff --git a/libpcsxcore/ix86_64/ix86-64.h b/libpcsxcore/ix86_64/ix86-64.h index 2915ae9b..009fa5a1 100644..100755 --- a/libpcsxcore/ix86_64/ix86-64.h +++ b/libpcsxcore/ix86_64/ix86-64.h @@ -1,1776 +1,1776 @@ -/*
- * ix86 definitions v0.6.2
- * Authors: linuzappz <linuzappz@pcsx.net>
- * alexey silinov
- * goldfinger
- * shadow < shadow@pcsx2.net >
- */
-
-#ifndef __IX86_H__
-#define __IX86_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "../psxcommon.h" // Basic types header
-#include <assert.h>
-#include <stdbool.h>
-
-#if defined(__MINGW32__)
-#define PCSX2_ALIGNED16(x) __declspec(align(16)) x
-#else
-#define PCSX2_ALIGNED16(x) x __attribute((aligned(16)))
-#endif
-
-
-#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
-typedef int x86IntRegType;
-#define EAX 0
-#define EBX 3
-#define ECX 1
-#define EDX 2
-#define ESI 6
-#define EDI 7
-#define EBP 5
-#define ESP 4
-
-#ifdef __x86_64__
-#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
-
-#define X86_TEMP RAX // don't allocate anything
-
-#ifdef _MSC_VER
-extern x86IntRegType g_x86savedregs[8];
-extern x86IntRegType g_x86tempregs[6];
-#else
-extern x86IntRegType g_x86savedregs[6];
-extern x86IntRegType g_x86tempregs[8];
-#endif
-
-extern x86IntRegType g_x86allregs[14]; // all registers that can be used by the recs
-extern x86IntRegType g_x868bitregs[11];
-extern x86IntRegType g_x86non8bitregs[3];
-
-#ifdef _MSC_VER
-#define X86ARG1 RCX
-#define X86ARG2 RDX
-#define X86ARG3 R8
-#define X86ARG4 R9
-#else
-#define X86ARG1 RDI
-#define X86ARG2 RSI
-#define X86ARG3 RDX
-#define X86ARG4 RCX
-#endif
-
-#else
-
-#define X86ARG1 EAX
-#define X86ARG2 ECX
-#define X86ARG3 EDX
-#define X86ARG4 EBX
-
-#endif // __x86_64__
-
-#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 X86_64ASSERT() assert(0)
-#define MEMADDR_(addr, oplen) (sptr)((uptr)(addr) - ((uptr)x86Ptr + ((u64)(oplen))))
-#define SPTR32(addr) ((addr) < 0x80000000L && (addr) >= -0x80000000L)
-#define UPTR32(addr) ((addr) < 0x100000000L)
-#define MEMADDR(addr, oplen) ({ sptr _a = MEMADDR_(addr, oplen); assert(SPTR32(_a)); _a; })
-#else
-#define X86_64ASSERT()
-#define SPTR32(a) 1
-#define UPTR32(a) 1
-#define MEMADDR(addr, oplen) (addr)
-#endif
-
-#ifdef __x86_64__
-#define Rex( w, r, x, b ) write8( 0x40 | ((w) << 3) | ((r) << 2) | ((x) << 1) | (b) )
-#else
-#define Rex(w,r,x,b) assert(0)
-#endif
-#define RexRXB(w, reg, index, base) if(w || (reg) >= 8 || (index) >= 8 || (base) >= 8 ) \
- Rex(w, (reg)>=8, (index)>=8, (base)>=8)
-#define RexR(w, reg) RexRXB(w, reg, 0, 0)
-#define RexB(w, base) RexRXB(w, 0, 0, base)
-#define RexRB(w, reg, base) RexRXB(w, reg, 0, base)
-
-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
-#define ModRM(mod, rm, reg) write8( ( mod << 6 ) | ( (rm & 7) << 3 ) | ( reg & 7 ) )
-#define SibSB(ss, rm, index) write8( ( ss << 6 ) | ( rm << 3 ) | ( 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, uptr from );
-
-void MEMADDR_OP(bool w, unsigned opl, u64 op, bool isreg, int reg, uptr p, sptr off);
-
-#define VAROP1(op) 1, op
-#define VAROP2(op1, op2) 2, (op1) | ((op2) << 8)
-
-//******************
-// 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( uptr to, x86IntRegType from );
-// mov m64 to r64
-void MOV64MtoR( x86IntRegType to, uptr from );
-// mov sign ext imm32 to m64
-void MOV64I32toM( uptr to, u32 from );
-// mov sign ext imm32 to r64
-void MOV64I32toR( x86IntRegType to, s32 from);
-// mov imm64 to r64
-void MOV64ItoR( x86IntRegType to, u64 from);
-// mov imm64 to [r64+off]
-void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset);
-// mov [r64+offset] to r64
-void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset );
-// mov [r64][r64*scale] to r64
-void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale);
-// mov r64 to [r64+offset]
-void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset );
-// mov r64 to [r64][r64*scale]
-void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale);
-
-// mov r32 to r32
-void MOV32RtoR( x86IntRegType to, x86IntRegType from );
-// mov r32 to m32
-void MOV32RtoM( uptr to, x86IntRegType from );
-// mov m32 to r32
-void MOV32MtoR( x86IntRegType to, uptr from );
-// mov [r32] to r32
-void MOV32RmtoR( x86IntRegType to, x86IntRegType from );
-void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset );
-// mov [r32][r32<<scale] to r32
-void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale );
-// mov [imm32(from2) + r32(from1)<<scale] to r32
-void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, int from2, int scale );
-// mov r32 to [r32]
-void MOV32RtoRm( x86IntRegType to, x86IntRegType from );
-// mov r32 to [r32][r32*scale]
-void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale );
-// mov imm32 to r32
-void MOV32ItoR( x86IntRegType to, u32 from );
-// mov imm32 to m32
-void MOV32ItoM( uptr to, u32 from );
-// mov imm32 to [r32+off]
-void MOV32ItoRmOffset( x86IntRegType to, u32 from, int offset);
-// mov r32 to [r32+off]
-void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset);
-
-// mov r16 to m16
-void MOV16RtoM( uptr to, x86IntRegType from );
-// mov m16 to r16
-void MOV16MtoR( x86IntRegType to, uptr from );
-// mov [r32] to r16
-void MOV16RmtoR( x86IntRegType to, x86IntRegType from ) ;
-void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset );
-// mov [imm32(from2) + r32(from1)<<scale] to r16
-void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale );
-// mov r16 to [r32]
-void MOV16RtoRm(x86IntRegType to, x86IntRegType from);
-// mov imm16 to m16
-void MOV16ItoM( uptr to, u16 from );
-/* mov r16 to [r32][r32*scale] */
-void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale);
-// mov imm16 to r16
-void MOV16ItoR( x86IntRegType to, u16 from );
-// mov imm16 to [r16+off]
-void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset);
-// mov r16 to [r16+off]
-void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset);
-
-// mov r8 to m8
-void MOV8RtoM( uptr to, x86IntRegType from );
-// mov m8 to r8
-void MOV8MtoR( x86IntRegType to, uptr from );
-// mov [r32] to r8
-void MOV8RmtoR(x86IntRegType to, x86IntRegType from);
-void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset);
-// mov r8 to [r32]
-void MOV8RtoRm(x86IntRegType to, x86IntRegType from);
-// mov imm8 to m8
-void MOV8ItoM( uptr to, u8 from );
-// mov imm8 to r8
-void MOV8ItoR( x86IntRegType to, u8 from );
-// mov imm8 to [r8+off]
-void MOV8ItoRmOffset( x86IntRegType to, u8 from, int offset);
-// mov r8 to [r8+off]
-void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset);
-
-// movsx r8 to r32
-void MOVSX32R8toR( x86IntRegType to, x86IntRegType from );
-void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from );
-void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset );
-// movsx m8 to r32
-void MOVSX32M8toR( x86IntRegType to, uptr from );
-// movsx r16 to r32
-void MOVSX32R16toR( x86IntRegType to, x86IntRegType from );
-void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from );
-void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset );
-// movsx m16 to r32
-void MOVSX32M16toR( x86IntRegType to, uptr from );
-
-// movzx r8 to r32
-void MOVZX32R8toR( x86IntRegType to, x86IntRegType from );
-void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from );
-void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset );
-// movzx m8 to r32
-void MOVZX32M8toR( x86IntRegType to, uptr from );
-// movzx r16 to r32
-void MOVZX32R16toR( x86IntRegType to, x86IntRegType from );
-void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from );
-void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset );
-// movzx m16 to r32
-void MOVZX32M16toR( x86IntRegType to, uptr from );
-
-#ifdef __x86_64__
-void MOVZX64R8toR( x86IntRegType to, x86IntRegType from );
-void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from );
-void MOVZX64Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset );
-// movzx m8 to r64
-void MOVZX64M8toR( x86IntRegType to, uptr from );
-// movzx r16 to r64
-void MOVZX64R16toR( x86IntRegType to, x86IntRegType from );
-void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from );
-void MOVZX64Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset );
-// movzx m16 to r64
-void MOVZX64M16toR( x86IntRegType to, uptr from );
-#endif
-
-// cmovbe r32 to r32
-void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovbe m32 to r32
-void CMOVBE32MtoR( x86IntRegType to, uptr from );
-// cmovb r32 to r32
-void CMOVB32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovb m32 to r32
-void CMOVB32MtoR( x86IntRegType to, uptr from );
-// cmovae r32 to r32
-void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovae m32 to r32
-void CMOVAE32MtoR( x86IntRegType to, uptr from );
-// cmova r32 to r32
-void CMOVA32RtoR( x86IntRegType to, x86IntRegType from );
-// cmova m32 to r32
-void CMOVA32MtoR( x86IntRegType to, uptr from );
-
-// cmovo r32 to r32
-void CMOVO32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovo m32 to r32
-void CMOVO32MtoR( x86IntRegType to, uptr from );
-// cmovp r32 to r32
-void CMOVP32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovp m32 to r32
-void CMOVP32MtoR( x86IntRegType to, uptr from );
-// cmovs r32 to r32
-void CMOVS32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovs m32 to r32
-void CMOVS32MtoR( x86IntRegType to, uptr from );
-// cmovno r32 to r32
-void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovno m32 to r32
-void CMOVNO32MtoR( x86IntRegType to, uptr from );
-// cmovnp r32 to r32
-void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovnp m32 to r32
-void CMOVNP32MtoR( x86IntRegType to, uptr from );
-// cmovns r32 to r32
-void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovns m32 to r32
-void CMOVNS32MtoR( x86IntRegType to, uptr from );
-
-// cmovne r32 to r32
-void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovne m32 to r32
-void CMOVNE32MtoR( x86IntRegType to, uptr from );
-// cmove r32 to r32
-void CMOVE32RtoR( x86IntRegType to, x86IntRegType from );
-// cmove m32 to r32
-void CMOVE32MtoR( x86IntRegType to, uptr from );
-// cmovg r32 to r32
-void CMOVG32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovg m32 to r32
-void CMOVG32MtoR( x86IntRegType to, uptr from );
-// cmovge r32 to r32
-void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovge m32 to r32
-void CMOVGE32MtoR( x86IntRegType to, uptr from );
-// cmovl r32 to r32
-void CMOVL32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovl m32 to r32
-void CMOVL32MtoR( x86IntRegType to, uptr from );
-// cmovle r32 to r32
-void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from );
-// cmovle m32 to r32
-void CMOVLE32MtoR( x86IntRegType to, uptr from );
-
-////////////////////////////////////
-// arithmetic instructions //
-////////////////////////////////////
-
-// add imm32 to r64
-void ADD64ItoR( x86IntRegType to, u32 from );
-// add m64 to r64
-void ADD64MtoR( x86IntRegType to, uptr from );
-
-// add imm32 to r32
-void ADD32ItoR( x86IntRegType to, u32 from );
-// add imm32 to m32
-void ADD32ItoM( uptr to, u32 from );
-// add imm32 to [r32+off]
-void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset);
-// add r32 to r32
-void ADD32RtoR( x86IntRegType to, x86IntRegType from );
-// add r32 to m32
-void ADD32RtoM( uptr to, x86IntRegType from );
-// add m32 to r32
-void ADD32MtoR( x86IntRegType to, uptr from );
-
-// add r16 to r16
-void ADD16RtoR( x86IntRegType to , x86IntRegType from );
-// add imm16 to r16
-void ADD16ItoR( x86IntRegType to, u16 from );
-// add imm16 to m16
-void ADD16ItoM( uptr to, u16 from );
-// add r16 to m16
-void ADD16RtoM( uptr to, x86IntRegType from );
-// add m16 to r16
-void ADD16MtoR( x86IntRegType to, uptr from );
-
-// add m8 to r8
-void ADD8MtoR( x86IntRegType to, uptr from );
-
-// adc imm32 to r32
-void ADC32ItoR( x86IntRegType to, u32 from );
-// adc imm32 to m32
-void ADC32ItoM( uptr to, u32 from );
-// adc r32 to r32
-void ADC32RtoR( x86IntRegType to, x86IntRegType from );
-// adc m32 to r32
-void ADC32MtoR( x86IntRegType to, uptr from );
-// adc r32 to m32
-void ADC32RtoM( uptr to, x86IntRegType from );
-
-// inc r32
-void INC32R( x86IntRegType to );
-// inc m32
-void INC32M( uptr to );
-// inc r16
-void INC16R( x86IntRegType to );
-// inc m16
-void INC16M( uptr to );
-
-// sub m64 to r64
-void SUB64MtoR( x86IntRegType to, uptr from );
-void SUB64ItoR( x86IntRegType to, u32 from );
-
-// sub imm32 to r32
-void SUB32ItoR( x86IntRegType to, u32 from );
-// sub imm32 to m32
-void SUB32ItoM( uptr to, u32 from ) ;
-// sub r32 to r32
-void SUB32RtoR( x86IntRegType to, x86IntRegType from );
-// sub m32 to r32
-void SUB32MtoR( x86IntRegType to, uptr from ) ;
-// sub r32 to m32
-void SUB32RtoM( uptr to, x86IntRegType from );
-// sub r16 to r16
-void SUB16RtoR( x86IntRegType to, u16 from );
-// sub imm16 to r16
-void SUB16ItoR( x86IntRegType to, u16 from );
-// sub imm16 to m16
-void SUB16ItoM( uptr to, u16 from ) ;
-// sub m16 to r16
-void SUB16MtoR( x86IntRegType to, uptr from );
-
-// sbb r64 to r64
-void SBB64RtoR( x86IntRegType to, x86IntRegType from );
-
-// sbb imm32 to r32
-void SBB32ItoR( x86IntRegType to, u32 from );
-// sbb imm32 to m32
-void SBB32ItoM( uptr to, u32 from );
-// sbb r32 to r32
-void SBB32RtoR( x86IntRegType to, x86IntRegType from );
-// sbb m32 to r32
-void SBB32MtoR( x86IntRegType to, uptr from );
-// sbb r32 to m32
-void SBB32RtoM( uptr to, x86IntRegType from );
-
-// dec r32
-void DEC32R( x86IntRegType to );
-// dec m32
-void DEC32M( uptr to );
-// dec r16
-void DEC16R( x86IntRegType to );
-// dec m16
-void DEC16M( uptr to );
-
-// mul eax by r32 to edx:eax
-void MUL32R( x86IntRegType from );
-// mul eax by m32 to edx:eax
-void MUL32M( uptr from );
-
-// imul eax by r32 to edx:eax
-void IMUL32R( x86IntRegType from );
-// imul eax by m32 to edx:eax
-void IMUL32M( uptr from );
-// imul r32 by r32 to r32
-void IMUL32RtoR( x86IntRegType to, x86IntRegType from );
-
-// div eax by r32 to edx:eax
-void DIV32R( x86IntRegType from );
-// div eax by m32 to edx:eax
-void DIV32M( uptr from );
-
-// idiv eax by r32 to edx:eax
-void IDIV32R( x86IntRegType from );
-// idiv eax by m32 to edx:eax
-void IDIV32M( uptr from );
-
-////////////////////////////////////
-// shifting instructions //
-////////////////////////////////////
-
-// shl imm8 to r64
-void SHL64ItoR( x86IntRegType to, u8 from );
-// shl cl to r64
-void SHL64CLtoR( x86IntRegType to );
-// shr imm8 to r64
-void SHR64ItoR( x86IntRegType to, u8 from );
-// shr cl to r64
-void SHR64CLtoR( x86IntRegType to );
-// sar imm8 to r64
-void SAR64ItoR( x86IntRegType to, u8 from );
-// sar cl to r64
-void SAR64CLtoR( x86IntRegType to );
-
-// shl imm8 to r32
-void SHL32ItoR( x86IntRegType to, u8 from );
-/* shl imm8 to m32 */
-void SHL32ItoM( uptr to, u8 from );
-// shl cl to r32
-void SHL32CLtoR( x86IntRegType to );
-
-// shl imm8 to r16
-void SHL16ItoR( x86IntRegType to, u8 from );
-// shl imm8 to r8
-void SHL8ItoR( x86IntRegType to, u8 from );
-
-// shr imm8 to r32
-void SHR32ItoR( x86IntRegType to, u8 from );
-/* shr imm8 to m32 */
-void SHR32ItoM( uptr to, u8 from );
-// shr cl to r32
-void SHR32CLtoR( x86IntRegType to );
-
-// shr imm8 to r8
-void SHR8ItoR( x86IntRegType to, u8 from );
-
-// sar imm8 to r32
-void SAR32ItoR( x86IntRegType to, u8 from );
-// sar imm8 to m32
-void SAR32ItoM( uptr to, u8 from );
-// sar cl to r32
-void SAR32CLtoR( x86IntRegType to );
-
-// sar imm8 to r16
-void SAR16ItoR( x86IntRegType to, u8 from );
-
-// ror imm8 to r32 (rotate right)
-void ROR32ItoR( x86IntRegType to,u8 from );
-
-void RCR32ItoR( x86IntRegType to,u8 from );
-// shld imm8 to r32
-void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift );
-// shrd imm8 to r32
-void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift );
-
-// sal imm8 to r32
-#define SAL32ItoR SHL32ItoR
-// sal cl to r32
-#define SAL32CLtoR SHL32CLtoR
-
-// logical instructions
-
-// or imm32 to r64
-void OR64ItoR( x86IntRegType to, u32 from );
-// or m64 to r64
-void OR64MtoR( x86IntRegType to, uptr from );
-// or r64 to r64
-void OR64RtoR( x86IntRegType to, x86IntRegType from );
-// or r32 to m64
-void OR64RtoM( uptr to, x86IntRegType from );
-
-// or imm32 to r32
-void OR32ItoR( x86IntRegType to, u32 from );
-// or imm32 to m32
-void OR32ItoM( uptr to, u32 from );
-// or r32 to r32
-void OR32RtoR( x86IntRegType to, x86IntRegType from );
-// or r32 to m32
-void OR32RtoM( uptr to, x86IntRegType from );
-// or m32 to r32
-void OR32MtoR( x86IntRegType to, uptr from );
-// or r16 to r16
-void OR16RtoR( x86IntRegType to, x86IntRegType from );
-// or imm16 to r16
-void OR16ItoR( x86IntRegType to, u16 from );
-// or imm16 to m16
-void OR16ItoM( uptr to, u16 from );
-// or m16 to r16
-void OR16MtoR( x86IntRegType to, uptr from );
-// or r16 to m16
-void OR16RtoM( uptr to, x86IntRegType from );
-
-// or r8 to r8
-void OR8RtoR( x86IntRegType to, x86IntRegType from );
-// or r8 to m8
-void OR8RtoM( uptr to, x86IntRegType from );
-// or imm8 to m8
-void OR8ItoM( uptr to, u8 from );
-// or m8 to r8
-void OR8MtoR( x86IntRegType to, uptr from );
-
-// xor imm32 to r64
-void XOR64ItoR( x86IntRegType to, u32 from );
-// xor r64 to r64
-void XOR64RtoR( x86IntRegType to, x86IntRegType from );
-// xor m64 to r64
-void XOR64MtoR( x86IntRegType to, uptr from );
-// xor r64 to r64
-void XOR64RtoR( x86IntRegType to, x86IntRegType from );
-// xor r64 to m64
-void XOR64RtoM( uptr to, x86IntRegType from );
-// xor imm32 to r32
-void XOR32ItoR( x86IntRegType to, u32 from );
-// xor imm32 to m32
-void XOR32ItoM( uptr to, u32 from );
-// xor r32 to r32
-void XOR32RtoR( x86IntRegType to, x86IntRegType from );
-// xor r16 to r16
-void XOR16RtoR( x86IntRegType to, x86IntRegType from );
-// xor r32 to m32
-void XOR32RtoM( uptr to, x86IntRegType from );
-// xor m32 to r32
-void XOR32MtoR( x86IntRegType to, uptr from );
-// xor r16 to m16
-void XOR16RtoM( uptr to, x86IntRegType from );
-// xor imm16 to r16
-void XOR16ItoR( x86IntRegType to, u16 from );
-
-// and imm32 to r64
-void AND64I32toR( x86IntRegType to, u32 from );
-// and m64 to r64
-void AND64MtoR( x86IntRegType to, uptr from );
-// and r64 to m64
-void AND64RtoM( uptr to, x86IntRegType from );
-// and r64 to r64
-void AND64RtoR( x86IntRegType to, x86IntRegType from );
-// and imm32 to m64
-void AND64I32toM( uptr to, u32 from );
-
-// and imm32 to r32
-void AND32ItoR( x86IntRegType to, u32 from );
-// and sign ext imm8 to r32
-void AND32I8toR( x86IntRegType to, u8 from );
-// and imm32 to m32
-void AND32ItoM( uptr to, u32 from );
-// and sign ext imm8 to m32
-void AND32I8toM( uptr to, u8 from );
-// and r32 to r32
-void AND32RtoR( x86IntRegType to, x86IntRegType from );
-// and r32 to m32
-void AND32RtoM( uptr to, x86IntRegType from );
-// and m32 to r32
-void AND32MtoR( x86IntRegType to, uptr from );
-// and r16 to r16
-void AND16RtoR( x86IntRegType to, x86IntRegType from );
-// and imm16 to r16
-void AND16ItoR( x86IntRegType to, u16 from );
-// and imm16 to m16
-void AND16ItoM( uptr to, u16 from );
-// and r16 to m16
-void AND16RtoM( uptr to, x86IntRegType from );
-// and m16 to r16
-void AND16MtoR( x86IntRegType to, uptr from );
-// and imm8 to r8
-void AND8ItoR( x86IntRegType to, u8 from );
-// and imm8 to m32
-void AND8ItoM( uptr to, u8 from );
-// and r8 to m8
-void AND8RtoM( uptr to, x86IntRegType from );
-// and m8 to r8
-void AND8MtoR( x86IntRegType to, uptr from );
-// and r8 to r8
-void AND8RtoR( x86IntRegType to, x86IntRegType from );
-
-// not r64
-void NOT64R( x86IntRegType from );
-// not r32
-void NOT32R( x86IntRegType from );
-// not m32
-void NOT32M( uptr from );
-// neg r64
-void NEG64R( x86IntRegType from );
-// neg r32
-void NEG32R( x86IntRegType from );
-// neg m32
-void NEG32M( uptr from );
-// neg r16
-void NEG16R( x86IntRegType from );
-
-////////////////////////////////////
-// jump instructions //
-////////////////////////////////////
-
-// jmp rel8
-u8* JMP8( u8 to );
-
-// jmp rel32
-u32* JMP32( uptr to );
-// jmp r32 (r64 if __x86_64__)
-void JMPR( x86IntRegType to );
-// jmp m32
-void JMP32M( uptr to );
-
-// jp rel8
-u8* JP8( u8 to );
-// jnp rel8
-u8* JNP8( u8 to );
-// je rel8
-u8* JE8( u8 to );
-// jz rel8
-u8* JZ8( u8 to );
-// jg rel8
-u8* JG8( u8 to );
-// jge rel8
-u8* JGE8( u8 to );
-// js rel8
-u8* JS8( u8 to );
-// jns rel8
-u8* JNS8( u8 to );
-// jl rel8
-u8* JL8( u8 to );
-// ja rel8
-u8* JA8( u8 to );
-// jae rel8
-u8* JAE8( u8 to );
-// jb rel8
-u8* JB8( u8 to );
-// jbe rel8
-u8* JBE8( u8 to );
-// jle rel8
-u8* JLE8( u8 to );
-// jne rel8
-u8* JNE8( u8 to );
-// jnz rel8
-u8* JNZ8( u8 to );
-// jng rel8
-u8* JNG8( u8 to );
-// jnge rel8
-u8* JNGE8( u8 to );
-// jnl rel8
-u8* JNL8( u8 to );
-// jnle rel8
-u8* JNLE8( u8 to );
-// jo rel8
-u8* JO8( u8 to );
-// jno rel8
-u8* JNO8( u8 to );
-
-// jb rel8
-u16* JB16( u16 to );
-
-// jb rel32
-u32* JB32( u32 to );
-// je rel32
-u32* JE32( u32 to );
-// jz rel32
-u32* JZ32( u32 to );
-// jg rel32
-u32* JG32( u32 to );
-// jge rel32
-u32* JGE32( u32 to );
-// jl rel32
-u32* JL32( u32 to );
-// jle rel32
-u32* JLE32( u32 to );
-// jae rel32
-u32* JAE32( u32 to );
-// jne rel32
-u32* JNE32( u32 to );
-// jnz rel32
-u32* JNZ32( u32 to );
-// jng rel32
-u32* JNG32( u32 to );
-// jnge rel32
-u32* JNGE32( u32 to );
-// jnl rel32
-u32* JNL32( u32 to );
-// jnle rel32
-u32* JNLE32( u32 to );
-// jo rel32
-u32* JO32( u32 to );
-// jno rel32
-u32* JNO32( u32 to );
-// js rel32
-u32* JS32( u32 to );
-
-// call func
-void CALLFunc( uptr func);
-// call rel32
-void CALL32( s32 to );
-// call r32
-void CALL32R( x86IntRegType to );
-// call m32
-void CALL64R( x86IntRegType to );
-
-
-////////////////////////////////////
-// misc instructions //
-////////////////////////////////////
-
-// cmp imm32 to r64
-void CMP64I32toR( x86IntRegType to, u32 from );
-// cmp m64 to r64
-void CMP64MtoR( x86IntRegType to, uptr from );
-// cmp r64 to r64
-void CMP64RtoR( x86IntRegType to, x86IntRegType from );
-
-// cmp imm32 to r32
-void CMP32ItoR( x86IntRegType to, u32 from );
-// cmp imm32 to m32
-void CMP32ItoM( uptr to, u32 from );
-// cmp r32 to r32
-void CMP32RtoR( x86IntRegType to, x86IntRegType from );
-// cmp m32 to r32
-void CMP32MtoR( x86IntRegType to, uptr from );
-// cmp imm32 to [r32]
-void CMP32I8toRm( x86IntRegType to, u8 from);
-// cmp imm32 to [r32+off]
-void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off);
-// cmp imm8 to [r32]
-void CMP32I8toM( uptr to, u8 from);
-
-// cmp imm16 to r16
-void CMP16ItoR( x86IntRegType to, u16 from );
-// cmp imm16 to m16
-void CMP16ItoM( uptr to, u16 from );
-// cmp r16 to r16
-void CMP16RtoR( x86IntRegType to, x86IntRegType from );
-// cmp m16 to r16
-void CMP16MtoR( x86IntRegType to, uptr from );
-
-// cmp imm8 to r8
-void CMP8ItoR( x86IntRegType to, u8 from );
-// cmp m8 to r8
-void CMP8MtoR( x86IntRegType to, uptr from );
-
-// test r64 to r64
-void TEST64RtoR( x86IntRegType to, x86IntRegType from );
-// test imm32 to r32
-void TEST32ItoR( x86IntRegType to, u32 from );
-// test imm32 to m32
-void TEST32ItoM( uptr to, u32 from );
-// test r32 to r32
-void TEST32RtoR( x86IntRegType to, x86IntRegType from );
-// test imm32 to [r32]
-void TEST32ItoRm( x86IntRegType to, u32 from );
-// test imm16 to r16
-void TEST16ItoR( x86IntRegType to, u16 from );
-// test r16 to r16
-void TEST16RtoR( x86IntRegType to, x86IntRegType from );
-// test imm8 to r8
-void TEST8ItoR( x86IntRegType to, u8 from );
-// test imm8 to r8
-void TEST8ItoM( uptr to, u8 from );
-
-// sets r8
-void SETS8R( x86IntRegType to );
-// setl r8
-void SETL8R( x86IntRegType to );
-// setge r8
-void SETGE8R( x86IntRegType to );
-// setge r8
-void SETG8R( x86IntRegType to );
-// seta r8
-void SETA8R( x86IntRegType to );
-// setae r8
-void SETAE8R( x86IntRegType to );
-// setb r8
-void SETB8R( x86IntRegType to );
-// setnz r8
-void SETNZ8R( x86IntRegType to );
-// setz r8
-void SETZ8R( x86IntRegType to );
-// sete r8
-void SETE8R( x86IntRegType to );
-
-// push imm32
-void PUSH32I( u32 from );
-
-#ifdef __x86_64__
-void PUSHI( u32 from );
-// push r64
-void PUSH64R( x86IntRegType from );
-// push m64
-void PUSH64M( uptr from );
-// pop r32
-void POP64R( x86IntRegType from );
-#else
-// push r32
-void PUSH32R( x86IntRegType from );
-// push m32
-void PUSH32M( u32 from );
-// push imm32
-void PUSH32I( u32 from );
-// pop r32
-void POP32R( x86IntRegType from );
-// pushad
-void PUSHA32( void );
-// popad
-void POPA32( void );
-#endif
-
-void PUSHR(x86IntRegType from);
-void POPR(x86IntRegType from);
-
-// pushfd
-void PUSHFD( void );
-// popfd
-void POPFD( void );
-// ret
-void RET( void );
-// ret (2-byte code used for misprediction)
-void RET2( void );
-
-void CBW();
-void CWDE();
-// cwd
-void CWD( void );
-// cdq
-void CDQ( void );
-// cdqe
-void CDQE( void );
-
-void LAHF();
-void SAHF();
-
-void BT32ItoR( x86IntRegType to, x86IntRegType from );
-void BSRRtoR(x86IntRegType to, x86IntRegType from);
-void BSWAP32R( x86IntRegType to );
-
-// to = from + offset
-void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset);
-void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset);
-
-// to = from0 + from1
-void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1);
-void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1);
-
-// to = from << scale (max is 3)
-void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale);
-void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale);
-
-//******************
-// FPU instructions
-//******************
-
-// fild m32 to fpu reg stack
-void FILD32( uptr from );
-// fistp m32 from fpu reg stack
-void FISTP32( uptr from );
-// fld m32 to fpu reg stack
-void FLD32( uptr from );
-// fld st(i)
-void FLD(int st);
-// fld1 (push +1.0f on the stack)
-void FLD1();
-// fld1 (push log_2 e on the stack)
-void FLDL2E();
-// fst m32 from fpu reg stack
-void FST32( uptr to );
-// fstp m32 from fpu reg stack
-void FSTP32( uptr to );
-// fstp st(i)
-void FSTP(int st);
-
-// fldcw fpu control word from m16
-void FLDCW( uptr from );
-// fstcw fpu control word to m16
-void FNSTCW( uptr to );
-void FXAM();
-void FDECSTP();
-// frndint
-void FRNDINT();
-void FXCH(int st);
-void F2XM1();
-void FSCALE();
-
-// fadd ST(src) to fpu reg stack ST(0)
-void FADD32Rto0( x86IntRegType src );
-// fadd ST(0) to fpu reg stack ST(src)
-void FADD320toR( x86IntRegType src );
-// fsub ST(src) to fpu reg stack ST(0)
-void FSUB32Rto0( x86IntRegType src );
-// fsub ST(0) to fpu reg stack ST(src)
-void FSUB320toR( x86IntRegType src );
-// fsubp -> 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( uptr from );
-// fsub m32 to fpu reg stack
-void FSUB32( uptr from );
-// fmul m32 to fpu reg stack
-void FMUL32( uptr from );
-// fdiv m32 to fpu reg stack
-void FDIV32( uptr 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( uptr 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( uptr from );
-void FNSTSWtoAX( void );
-
-// probably a little extreme here, but x86-64 should NOT use MMX
-#ifdef __x86_64__
-
-#define MMXONLY(code)
-
-#else
-
-#define MMXONLY(code) code
-
-//******************
-// MMX instructions
-//******************
-
-// r64 = mm
-
-// movq m64 to r64
-void MOVQMtoR( x86MMXRegType to, uptr from );
-// movq r64 to m64
-void MOVQRtoM( uptr 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, uptr from );
-// pandn r64 to r64
-void PANDNRtoR( x86MMXRegType to, x86MMXRegType from );
-// pandn r64 to r64
-void PANDNMtoR( x86MMXRegType to, uptr from );
-// por r64 to r64
-void PORRtoR( x86MMXRegType to, x86MMXRegType from );
-// por m64 to r64
-void PORMtoR( x86MMXRegType to, uptr from );
-// pxor r64 to r64
-void PXORRtoR( x86MMXRegType to, x86MMXRegType from );
-// pxor m64 to r64
-void PXORMtoR( x86MMXRegType to, uptr from );
-
-// psllq r64 to r64
-void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from );
-// psllq m64 to r64
-void PSLLQMtoR( x86MMXRegType to, uptr 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, uptr 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, uptr from );
-// paddusw r64 to r64
-void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from );
-// paddusw m64 to r64
-void PADDUSWMtoR( x86MMXRegType to, uptr from );
-
-// paddb r64 to r64
-void PADDBRtoR( x86MMXRegType to, x86MMXRegType from );
-// paddb m64 to r64
-void PADDBMtoR( x86MMXRegType to, uptr from );
-// paddw r64 to r64
-void PADDWRtoR( x86MMXRegType to, x86MMXRegType from );
-// paddw m64 to r64
-void PADDWMtoR( x86MMXRegType to, uptr from );
-// paddd r64 to r64
-void PADDDRtoR( x86MMXRegType to, x86MMXRegType from );
-// paddd m64 to r64
-void PADDDMtoR( x86MMXRegType to, uptr from );
-void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from );
-void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from );
-
-// paddq m64 to r64 (sse2 only?)
-void PADDQMtoR( x86MMXRegType to, uptr 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, uptr from );
-
-// psubq m64 to r64 (sse2 only?)
-void PSUBQMtoR( x86MMXRegType to, uptr from );
-// psubq r64 to r64 (sse2 only?)
-void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from );
-
-// pmuludq m64 to r64 (sse2 only?)
-void PMULUDQMtoR( x86MMXRegType to, uptr 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, uptr from );
-void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from );
-void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from );
-void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from );
-void PCMPGTDMtoR( x86MMXRegType to, uptr 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, uptr from );
-void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from );
-void PUNPCKHDQMtoR( x86MMXRegType to, uptr 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, uptr from );
-void MOVDMMXtoM( uptr 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, uptr 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);
-
-void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from);
-void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from);
-
-#endif // !__x86_64__
-
-//*********************
-// SSE instructions *
-//*********************
-void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from );
-void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from );
-
-void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr 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, int offset );
-void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset );
-
-void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from );
-void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from );
-
-void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from );
-void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from );
-void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset );
-void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset );
-
-void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from );
-void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from );
-void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset );
-void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset );
-
-void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from );
-void SSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset );
-void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from );
-void SSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int 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, int offset );
-void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int 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, int offset );
-void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset );
-
-void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset );
-void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset );
-
-void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_RCPPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_RCPSS_M32_to_XMM( x86SSERegType to, uptr from );
-
-void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_XORPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_ANDPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_ADDPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_ADDSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_SUBPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_SUBSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MULPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MULSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-#ifndef __x86_64__
-void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from );
-void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from );
-void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from );
-void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from );
-void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from );
-#endif
-void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from );
-void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from);
-void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from);
-void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from);
-void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from);
-
-void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSE_MAXPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MAXSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_MINSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, uptr from );
-void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from, u8 imm8 );
-void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 );
-void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_DIVPS_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE_DIVSS_M32_to_XMM( x86SSERegType to, uptr 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, uptr from, u8 imm8 );
-
-void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 );
-void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 );
-void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 );
-void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 );
-
-void SSE_STMXCSR( uptr from );
-void SSE_LDMXCSR( uptr from );
-
-
-//*********************
-// SSE 2 Instructions*
-//*********************
-void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from);
-void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from);
-
-void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE2_MOVDQU_XMM_to_M128( uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from );
-void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PAND_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PANDN_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from );
-void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from);
-void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr from);
-
-//**********************************************************************************/
-//PUNPCKHWD: Unpack 16bit high
-//**********************************************************************************
-void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from);
-
-// mult by half words
-void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from );
-void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from );
-///////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//PCMPxx: Compare Packed Integers *
-//**********************************************************************************
-void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr from );
-void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from );
-void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from );
-//**********************************************************************************/
-//MOVD: Move Dword(32bit) to /from XMM reg *
-//**********************************************************************************
-void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr 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, int 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, int offset );
-
-#ifdef __x86_64__
-void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from );
-void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from );
-#endif
-
-//**********************************************************************************/
-//POR : SSE Bitwise OR *
-//**********************************************************************************
-void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr from );
-
-void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from);
-void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr 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, uptr from );
-void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from );
-void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset );
-void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset );
-
-void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from );
-void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from );
-void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr 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, int offset );
-void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset );
-
-void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from );
-void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from );
-void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from );
-void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr 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, uptr from);
-void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
-void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from);
-
-void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
-
-//*********************
-// 3DNOW instructions *
-//*********************
-void FEMMS( void );
-void PFCMPEQMtoR( x86IntRegType to, uptr from );
-void PFCMPGTMtoR( x86IntRegType to, uptr from );
-void PFCMPGEMtoR( x86IntRegType to, uptr from );
-void PFADDMtoR( x86IntRegType to, uptr from );
-void PFADDRtoR( x86IntRegType to, x86IntRegType from );
-void PFSUBMtoR( x86IntRegType to, uptr from );
-void PFSUBRtoR( x86IntRegType to, x86IntRegType from );
-void PFMULMtoR( x86IntRegType to, uptr from );
-void PFMULRtoR( x86IntRegType to, x86IntRegType from );
-void PFRCPMtoR( x86IntRegType to, uptr 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, uptr from );
-void PF2IDRtoR( x86IntRegType to, x86IntRegType from );
-void PI2FDMtoR( x86IntRegType to, uptr from );
-void PI2FDRtoR( x86IntRegType to, x86IntRegType from );
-void PFMAXMtoR( x86IntRegType to, uptr from );
-void PFMAXRtoR( x86IntRegType to, x86IntRegType from );
-void PFMINMtoR( x86IntRegType to, uptr 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, uptr from);
-void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from);
-void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset );
-void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, int offset );
-
-#ifndef __x86_64__
-void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from);
-void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from);
-#endif
-
-/* 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, uptr from );
-void SSE2EMU_MOVD_XMM_to_M32( uptr to, x86SSERegType from );
-void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from );
-
-////////////////////////////////////////////////////
-#ifdef _DEBUG
-#define WRITECHECK() CheckX86Ptr()
-#else
-#define WRITECHECK()
-#endif
-
-#define writeVAL(val) ({ \
- WRITECHECK(); \
- *(typeof(val)*)x86Ptr = (val); \
- x86Ptr += sizeof(val); \
- (void)0; \
- })
-
-#define write8(val ) writeVAL((u8)(val))
-#define write16(val ) writeVAL((u16)(val))
-#define write32( val ) writeVAL((u32)(val))
-#define write64( val ) writeVAL((u64)(val))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __IX86_H__
+/* + * ix86 definitions v0.6.2 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + * goldfinger + * shadow < shadow@pcsx2.net > + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../psxcommon.h" // Basic types header +#include <assert.h> +#include <stdbool.h> + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + + +#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 +typedef int x86IntRegType; +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 + +#ifdef __x86_64__ +#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 + +#define X86_TEMP RAX // don't allocate anything + +#ifdef _MSC_VER +extern x86IntRegType g_x86savedregs[8]; +extern x86IntRegType g_x86tempregs[6]; +#else +extern x86IntRegType g_x86savedregs[6]; +extern x86IntRegType g_x86tempregs[8]; +#endif + +extern x86IntRegType g_x86allregs[14]; // all registers that can be used by the recs +extern x86IntRegType g_x868bitregs[11]; +extern x86IntRegType g_x86non8bitregs[3]; + +#ifdef _MSC_VER +#define X86ARG1 RCX +#define X86ARG2 RDX +#define X86ARG3 R8 +#define X86ARG4 R9 +#else +#define X86ARG1 RDI +#define X86ARG2 RSI +#define X86ARG3 RDX +#define X86ARG4 RCX +#endif + +#else + +#define X86ARG1 EAX +#define X86ARG2 ECX +#define X86ARG3 EDX +#define X86ARG4 EBX + +#endif // __x86_64__ + +#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 X86_64ASSERT() assert(0) +#define MEMADDR_(addr, oplen) (sptr)((uptr)(addr) - ((uptr)x86Ptr + ((u64)(oplen)))) +#define SPTR32(addr) ((addr) < 0x80000000L && (addr) >= -0x80000000L) +#define UPTR32(addr) ((addr) < 0x100000000L) +#define MEMADDR(addr, oplen) ({ sptr _a = MEMADDR_(addr, oplen); assert(SPTR32(_a)); _a; }) +#else +#define X86_64ASSERT() +#define SPTR32(a) 1 +#define UPTR32(a) 1 +#define MEMADDR(addr, oplen) (addr) +#endif + +#ifdef __x86_64__ +#define Rex( w, r, x, b ) write8( 0x40 | ((w) << 3) | ((r) << 2) | ((x) << 1) | (b) ) +#else +#define Rex(w,r,x,b) assert(0) +#endif +#define RexRXB(w, reg, index, base) if(w || (reg) >= 8 || (index) >= 8 || (base) >= 8 ) \ + Rex(w, (reg)>=8, (index)>=8, (base)>=8) +#define RexR(w, reg) RexRXB(w, reg, 0, 0) +#define RexB(w, base) RexRXB(w, 0, 0, base) +#define RexRB(w, reg, base) RexRXB(w, reg, 0, base) + +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 +#define ModRM(mod, rm, reg) write8( ( mod << 6 ) | ( (rm & 7) << 3 ) | ( reg & 7 ) ) +#define SibSB(ss, rm, index) write8( ( ss << 6 ) | ( rm << 3 ) | ( 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, uptr from ); + +void MEMADDR_OP(bool w, unsigned opl, u64 op, bool isreg, int reg, uptr p, sptr off); + +#define VAROP1(op) 1, op +#define VAROP2(op1, op2) 2, (op1) | ((op2) << 8) + +//****************** +// 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( uptr to, x86IntRegType from ); +// mov m64 to r64 +void MOV64MtoR( x86IntRegType to, uptr from ); +// mov sign ext imm32 to m64 +void MOV64I32toM( uptr to, u32 from ); +// mov sign ext imm32 to r64 +void MOV64I32toR( x86IntRegType to, s32 from); +// mov imm64 to r64 +void MOV64ItoR( x86IntRegType to, u64 from); +// mov imm64 to [r64+off] +void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset); +// mov [r64+offset] to r64 +void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset ); +// mov [r64][r64*scale] to r64 +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale); +// mov r64 to [r64+offset] +void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset ); +// mov r64 to [r64][r64*scale] +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale); + +// mov r32 to r32 +void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +void MOV32RtoM( uptr to, x86IntRegType from ); +// mov m32 to r32 +void MOV32MtoR( x86IntRegType to, uptr from ); +// mov [r32] to r32 +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ); +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ); +// mov [r32][r32<<scale] to r32 +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale ); +// mov [imm32(from2) + r32(from1)<<scale] to r32 +void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, int from2, int scale ); +// mov r32 to [r32] +void MOV32RtoRm( x86IntRegType to, x86IntRegType from ); +// mov r32 to [r32][r32*scale] +void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale ); +// mov imm32 to r32 +void MOV32ItoR( x86IntRegType to, u32 from ); +// mov imm32 to m32 +void MOV32ItoM( uptr to, u32 from ); +// mov imm32 to [r32+off] +void MOV32ItoRmOffset( x86IntRegType to, u32 from, int offset); +// mov r32 to [r32+off] +void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset); + +// mov r16 to m16 +void MOV16RtoM( uptr to, x86IntRegType from ); +// mov m16 to r16 +void MOV16MtoR( x86IntRegType to, uptr from ); +// mov [r32] to r16 +void MOV16RmtoR( x86IntRegType to, x86IntRegType from ) ; +void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ); +// mov [imm32(from2) + r32(from1)<<scale] to r16 +void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ); +// mov r16 to [r32] +void MOV16RtoRm(x86IntRegType to, x86IntRegType from); +// mov imm16 to m16 +void MOV16ItoM( uptr to, u16 from ); +/* mov r16 to [r32][r32*scale] */ +void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale); +// mov imm16 to r16 +void MOV16ItoR( x86IntRegType to, u16 from ); +// mov imm16 to [r16+off] +void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset); +// mov r16 to [r16+off] +void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset); + +// mov r8 to m8 +void MOV8RtoM( uptr to, x86IntRegType from ); +// mov m8 to r8 +void MOV8MtoR( x86IntRegType to, uptr from ); +// mov [r32] to r8 +void MOV8RmtoR(x86IntRegType to, x86IntRegType from); +void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset); +// mov r8 to [r32] +void MOV8RtoRm(x86IntRegType to, x86IntRegType from); +// mov imm8 to m8 +void MOV8ItoM( uptr to, u8 from ); +// mov imm8 to r8 +void MOV8ItoR( x86IntRegType to, u8 from ); +// mov imm8 to [r8+off] +void MOV8ItoRmOffset( x86IntRegType to, u8 from, int offset); +// mov r8 to [r8+off] +void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset); + +// movsx r8 to r32 +void MOVSX32R8toR( x86IntRegType to, x86IntRegType from ); +void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from ); +void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ); +// movsx m8 to r32 +void MOVSX32M8toR( x86IntRegType to, uptr from ); +// movsx r16 to r32 +void MOVSX32R16toR( x86IntRegType to, x86IntRegType from ); +void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from ); +void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ); +// movsx m16 to r32 +void MOVSX32M16toR( x86IntRegType to, uptr from ); + +// movzx r8 to r32 +void MOVZX32R8toR( x86IntRegType to, x86IntRegType from ); +void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from ); +void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ); +// movzx m8 to r32 +void MOVZX32M8toR( x86IntRegType to, uptr from ); +// movzx r16 to r32 +void MOVZX32R16toR( x86IntRegType to, x86IntRegType from ); +void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from ); +void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ); +// movzx m16 to r32 +void MOVZX32M16toR( x86IntRegType to, uptr from ); + +#ifdef __x86_64__ +void MOVZX64R8toR( x86IntRegType to, x86IntRegType from ); +void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from ); +void MOVZX64Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ); +// movzx m8 to r64 +void MOVZX64M8toR( x86IntRegType to, uptr from ); +// movzx r16 to r64 +void MOVZX64R16toR( x86IntRegType to, x86IntRegType from ); +void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from ); +void MOVZX64Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ); +// movzx m16 to r64 +void MOVZX64M16toR( x86IntRegType to, uptr from ); +#endif + +// cmovbe r32 to r32 +void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovbe m32 to r32 +void CMOVBE32MtoR( x86IntRegType to, uptr from ); +// cmovb r32 to r32 +void CMOVB32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovb m32 to r32 +void CMOVB32MtoR( x86IntRegType to, uptr from ); +// cmovae r32 to r32 +void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovae m32 to r32 +void CMOVAE32MtoR( x86IntRegType to, uptr from ); +// cmova r32 to r32 +void CMOVA32RtoR( x86IntRegType to, x86IntRegType from ); +// cmova m32 to r32 +void CMOVA32MtoR( x86IntRegType to, uptr from ); + +// cmovo r32 to r32 +void CMOVO32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovo m32 to r32 +void CMOVO32MtoR( x86IntRegType to, uptr from ); +// cmovp r32 to r32 +void CMOVP32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovp m32 to r32 +void CMOVP32MtoR( x86IntRegType to, uptr from ); +// cmovs r32 to r32 +void CMOVS32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovs m32 to r32 +void CMOVS32MtoR( x86IntRegType to, uptr from ); +// cmovno r32 to r32 +void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovno m32 to r32 +void CMOVNO32MtoR( x86IntRegType to, uptr from ); +// cmovnp r32 to r32 +void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovnp m32 to r32 +void CMOVNP32MtoR( x86IntRegType to, uptr from ); +// cmovns r32 to r32 +void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovns m32 to r32 +void CMOVNS32MtoR( x86IntRegType to, uptr from ); + +// cmovne r32 to r32 +void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovne m32 to r32 +void CMOVNE32MtoR( x86IntRegType to, uptr from ); +// cmove r32 to r32 +void CMOVE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmove m32 to r32 +void CMOVE32MtoR( x86IntRegType to, uptr from ); +// cmovg r32 to r32 +void CMOVG32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovg m32 to r32 +void CMOVG32MtoR( x86IntRegType to, uptr from ); +// cmovge r32 to r32 +void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovge m32 to r32 +void CMOVGE32MtoR( x86IntRegType to, uptr from ); +// cmovl r32 to r32 +void CMOVL32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovl m32 to r32 +void CMOVL32MtoR( x86IntRegType to, uptr from ); +// cmovle r32 to r32 +void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovle m32 to r32 +void CMOVLE32MtoR( x86IntRegType to, uptr from ); + +//////////////////////////////////// +// arithmetic instructions // +//////////////////////////////////// + +// add imm32 to r64 +void ADD64ItoR( x86IntRegType to, u32 from ); +// add m64 to r64 +void ADD64MtoR( x86IntRegType to, uptr from ); + +// add imm32 to r32 +void ADD32ItoR( x86IntRegType to, u32 from ); +// add imm32 to m32 +void ADD32ItoM( uptr to, u32 from ); +// add imm32 to [r32+off] +void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset); +// add r32 to r32 +void ADD32RtoR( x86IntRegType to, x86IntRegType from ); +// add r32 to m32 +void ADD32RtoM( uptr to, x86IntRegType from ); +// add m32 to r32 +void ADD32MtoR( x86IntRegType to, uptr from ); + +// add r16 to r16 +void ADD16RtoR( x86IntRegType to , x86IntRegType from ); +// add imm16 to r16 +void ADD16ItoR( x86IntRegType to, u16 from ); +// add imm16 to m16 +void ADD16ItoM( uptr to, u16 from ); +// add r16 to m16 +void ADD16RtoM( uptr to, x86IntRegType from ); +// add m16 to r16 +void ADD16MtoR( x86IntRegType to, uptr from ); + +// add m8 to r8 +void ADD8MtoR( x86IntRegType to, uptr from ); + +// adc imm32 to r32 +void ADC32ItoR( x86IntRegType to, u32 from ); +// adc imm32 to m32 +void ADC32ItoM( uptr to, u32 from ); +// adc r32 to r32 +void ADC32RtoR( x86IntRegType to, x86IntRegType from ); +// adc m32 to r32 +void ADC32MtoR( x86IntRegType to, uptr from ); +// adc r32 to m32 +void ADC32RtoM( uptr to, x86IntRegType from ); + +// inc r32 +void INC32R( x86IntRegType to ); +// inc m32 +void INC32M( uptr to ); +// inc r16 +void INC16R( x86IntRegType to ); +// inc m16 +void INC16M( uptr to ); + +// sub m64 to r64 +void SUB64MtoR( x86IntRegType to, uptr from ); +void SUB64ItoR( x86IntRegType to, u32 from ); + +// sub imm32 to r32 +void SUB32ItoR( x86IntRegType to, u32 from ); +// sub imm32 to m32 +void SUB32ItoM( uptr to, u32 from ) ; +// sub r32 to r32 +void SUB32RtoR( x86IntRegType to, x86IntRegType from ); +// sub m32 to r32 +void SUB32MtoR( x86IntRegType to, uptr from ) ; +// sub r32 to m32 +void SUB32RtoM( uptr to, x86IntRegType from ); +// sub r16 to r16 +void SUB16RtoR( x86IntRegType to, u16 from ); +// sub imm16 to r16 +void SUB16ItoR( x86IntRegType to, u16 from ); +// sub imm16 to m16 +void SUB16ItoM( uptr to, u16 from ) ; +// sub m16 to r16 +void SUB16MtoR( x86IntRegType to, uptr from ); + +// sbb r64 to r64 +void SBB64RtoR( x86IntRegType to, x86IntRegType from ); + +// sbb imm32 to r32 +void SBB32ItoR( x86IntRegType to, u32 from ); +// sbb imm32 to m32 +void SBB32ItoM( uptr to, u32 from ); +// sbb r32 to r32 +void SBB32RtoR( x86IntRegType to, x86IntRegType from ); +// sbb m32 to r32 +void SBB32MtoR( x86IntRegType to, uptr from ); +// sbb r32 to m32 +void SBB32RtoM( uptr to, x86IntRegType from ); + +// dec r32 +void DEC32R( x86IntRegType to ); +// dec m32 +void DEC32M( uptr to ); +// dec r16 +void DEC16R( x86IntRegType to ); +// dec m16 +void DEC16M( uptr to ); + +// mul eax by r32 to edx:eax +void MUL32R( x86IntRegType from ); +// mul eax by m32 to edx:eax +void MUL32M( uptr from ); + +// imul eax by r32 to edx:eax +void IMUL32R( x86IntRegType from ); +// imul eax by m32 to edx:eax +void IMUL32M( uptr from ); +// imul r32 by r32 to r32 +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ); + +// div eax by r32 to edx:eax +void DIV32R( x86IntRegType from ); +// div eax by m32 to edx:eax +void DIV32M( uptr from ); + +// idiv eax by r32 to edx:eax +void IDIV32R( x86IntRegType from ); +// idiv eax by m32 to edx:eax +void IDIV32M( uptr from ); + +//////////////////////////////////// +// shifting instructions // +//////////////////////////////////// + +// shl imm8 to r64 +void SHL64ItoR( x86IntRegType to, u8 from ); +// shl cl to r64 +void SHL64CLtoR( x86IntRegType to ); +// shr imm8 to r64 +void SHR64ItoR( x86IntRegType to, u8 from ); +// shr cl to r64 +void SHR64CLtoR( x86IntRegType to ); +// sar imm8 to r64 +void SAR64ItoR( x86IntRegType to, u8 from ); +// sar cl to r64 +void SAR64CLtoR( x86IntRegType to ); + +// shl imm8 to r32 +void SHL32ItoR( x86IntRegType to, u8 from ); +/* shl imm8 to m32 */ +void SHL32ItoM( uptr to, u8 from ); +// shl cl to r32 +void SHL32CLtoR( x86IntRegType to ); + +// shl imm8 to r16 +void SHL16ItoR( x86IntRegType to, u8 from ); +// shl imm8 to r8 +void SHL8ItoR( x86IntRegType to, u8 from ); + +// shr imm8 to r32 +void SHR32ItoR( x86IntRegType to, u8 from ); +/* shr imm8 to m32 */ +void SHR32ItoM( uptr to, u8 from ); +// shr cl to r32 +void SHR32CLtoR( x86IntRegType to ); + +// shr imm8 to r8 +void SHR8ItoR( x86IntRegType to, u8 from ); + +// sar imm8 to r32 +void SAR32ItoR( x86IntRegType to, u8 from ); +// sar imm8 to m32 +void SAR32ItoM( uptr to, u8 from ); +// sar cl to r32 +void SAR32CLtoR( x86IntRegType to ); + +// sar imm8 to r16 +void SAR16ItoR( x86IntRegType to, u8 from ); + +// ror imm8 to r32 (rotate right) +void ROR32ItoR( x86IntRegType to,u8 from ); + +void RCR32ItoR( x86IntRegType to,u8 from ); +// shld imm8 to r32 +void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ); +// shrd imm8 to r32 +void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ); + +// sal imm8 to r32 +#define SAL32ItoR SHL32ItoR +// sal cl to r32 +#define SAL32CLtoR SHL32CLtoR + +// logical instructions + +// or imm32 to r64 +void OR64ItoR( x86IntRegType to, u32 from ); +// or m64 to r64 +void OR64MtoR( x86IntRegType to, uptr from ); +// or r64 to r64 +void OR64RtoR( x86IntRegType to, x86IntRegType from ); +// or r32 to m64 +void OR64RtoM( uptr to, x86IntRegType from ); + +// or imm32 to r32 +void OR32ItoR( x86IntRegType to, u32 from ); +// or imm32 to m32 +void OR32ItoM( uptr to, u32 from ); +// or r32 to r32 +void OR32RtoR( x86IntRegType to, x86IntRegType from ); +// or r32 to m32 +void OR32RtoM( uptr to, x86IntRegType from ); +// or m32 to r32 +void OR32MtoR( x86IntRegType to, uptr from ); +// or r16 to r16 +void OR16RtoR( x86IntRegType to, x86IntRegType from ); +// or imm16 to r16 +void OR16ItoR( x86IntRegType to, u16 from ); +// or imm16 to m16 +void OR16ItoM( uptr to, u16 from ); +// or m16 to r16 +void OR16MtoR( x86IntRegType to, uptr from ); +// or r16 to m16 +void OR16RtoM( uptr to, x86IntRegType from ); + +// or r8 to r8 +void OR8RtoR( x86IntRegType to, x86IntRegType from ); +// or r8 to m8 +void OR8RtoM( uptr to, x86IntRegType from ); +// or imm8 to m8 +void OR8ItoM( uptr to, u8 from ); +// or m8 to r8 +void OR8MtoR( x86IntRegType to, uptr from ); + +// xor imm32 to r64 +void XOR64ItoR( x86IntRegType to, u32 from ); +// xor r64 to r64 +void XOR64RtoR( x86IntRegType to, x86IntRegType from ); +// xor m64 to r64 +void XOR64MtoR( x86IntRegType to, uptr from ); +// xor r64 to r64 +void XOR64RtoR( x86IntRegType to, x86IntRegType from ); +// xor r64 to m64 +void XOR64RtoM( uptr to, x86IntRegType from ); +// xor imm32 to r32 +void XOR32ItoR( x86IntRegType to, u32 from ); +// xor imm32 to m32 +void XOR32ItoM( uptr to, u32 from ); +// xor r32 to r32 +void XOR32RtoR( x86IntRegType to, x86IntRegType from ); +// xor r16 to r16 +void XOR16RtoR( x86IntRegType to, x86IntRegType from ); +// xor r32 to m32 +void XOR32RtoM( uptr to, x86IntRegType from ); +// xor m32 to r32 +void XOR32MtoR( x86IntRegType to, uptr from ); +// xor r16 to m16 +void XOR16RtoM( uptr to, x86IntRegType from ); +// xor imm16 to r16 +void XOR16ItoR( x86IntRegType to, u16 from ); + +// and imm32 to r64 +void AND64I32toR( x86IntRegType to, u32 from ); +// and m64 to r64 +void AND64MtoR( x86IntRegType to, uptr from ); +// and r64 to m64 +void AND64RtoM( uptr to, x86IntRegType from ); +// and r64 to r64 +void AND64RtoR( x86IntRegType to, x86IntRegType from ); +// and imm32 to m64 +void AND64I32toM( uptr to, u32 from ); + +// and imm32 to r32 +void AND32ItoR( x86IntRegType to, u32 from ); +// and sign ext imm8 to r32 +void AND32I8toR( x86IntRegType to, u8 from ); +// and imm32 to m32 +void AND32ItoM( uptr to, u32 from ); +// and sign ext imm8 to m32 +void AND32I8toM( uptr to, u8 from ); +// and r32 to r32 +void AND32RtoR( x86IntRegType to, x86IntRegType from ); +// and r32 to m32 +void AND32RtoM( uptr to, x86IntRegType from ); +// and m32 to r32 +void AND32MtoR( x86IntRegType to, uptr from ); +// and r16 to r16 +void AND16RtoR( x86IntRegType to, x86IntRegType from ); +// and imm16 to r16 +void AND16ItoR( x86IntRegType to, u16 from ); +// and imm16 to m16 +void AND16ItoM( uptr to, u16 from ); +// and r16 to m16 +void AND16RtoM( uptr to, x86IntRegType from ); +// and m16 to r16 +void AND16MtoR( x86IntRegType to, uptr from ); +// and imm8 to r8 +void AND8ItoR( x86IntRegType to, u8 from ); +// and imm8 to m32 +void AND8ItoM( uptr to, u8 from ); +// and r8 to m8 +void AND8RtoM( uptr to, x86IntRegType from ); +// and m8 to r8 +void AND8MtoR( x86IntRegType to, uptr from ); +// and r8 to r8 +void AND8RtoR( x86IntRegType to, x86IntRegType from ); + +// not r64 +void NOT64R( x86IntRegType from ); +// not r32 +void NOT32R( x86IntRegType from ); +// not m32 +void NOT32M( uptr from ); +// neg r64 +void NEG64R( x86IntRegType from ); +// neg r32 +void NEG32R( x86IntRegType from ); +// neg m32 +void NEG32M( uptr from ); +// neg r16 +void NEG16R( x86IntRegType from ); + +//////////////////////////////////// +// jump instructions // +//////////////////////////////////// + +// jmp rel8 +u8* JMP8( u8 to ); + +// jmp rel32 +u32* JMP32( uptr to ); +// jmp r32 (r64 if __x86_64__) +void JMPR( x86IntRegType to ); +// jmp m32 +void JMP32M( uptr to ); + +// jp rel8 +u8* JP8( u8 to ); +// jnp rel8 +u8* JNP8( u8 to ); +// je rel8 +u8* JE8( u8 to ); +// jz rel8 +u8* JZ8( u8 to ); +// jg rel8 +u8* JG8( u8 to ); +// jge rel8 +u8* JGE8( u8 to ); +// js rel8 +u8* JS8( u8 to ); +// jns rel8 +u8* JNS8( u8 to ); +// jl rel8 +u8* JL8( u8 to ); +// ja rel8 +u8* JA8( u8 to ); +// jae rel8 +u8* JAE8( u8 to ); +// jb rel8 +u8* JB8( u8 to ); +// jbe rel8 +u8* JBE8( u8 to ); +// jle rel8 +u8* JLE8( u8 to ); +// jne rel8 +u8* JNE8( u8 to ); +// jnz rel8 +u8* JNZ8( u8 to ); +// jng rel8 +u8* JNG8( u8 to ); +// jnge rel8 +u8* JNGE8( u8 to ); +// jnl rel8 +u8* JNL8( u8 to ); +// jnle rel8 +u8* JNLE8( u8 to ); +// jo rel8 +u8* JO8( u8 to ); +// jno rel8 +u8* JNO8( u8 to ); + +// jb rel8 +u16* JB16( u16 to ); + +// jb rel32 +u32* JB32( u32 to ); +// je rel32 +u32* JE32( u32 to ); +// jz rel32 +u32* JZ32( u32 to ); +// jg rel32 +u32* JG32( u32 to ); +// jge rel32 +u32* JGE32( u32 to ); +// jl rel32 +u32* JL32( u32 to ); +// jle rel32 +u32* JLE32( u32 to ); +// jae rel32 +u32* JAE32( u32 to ); +// jne rel32 +u32* JNE32( u32 to ); +// jnz rel32 +u32* JNZ32( u32 to ); +// jng rel32 +u32* JNG32( u32 to ); +// jnge rel32 +u32* JNGE32( u32 to ); +// jnl rel32 +u32* JNL32( u32 to ); +// jnle rel32 +u32* JNLE32( u32 to ); +// jo rel32 +u32* JO32( u32 to ); +// jno rel32 +u32* JNO32( u32 to ); +// js rel32 +u32* JS32( u32 to ); + +// call func +void CALLFunc( uptr func); +// call rel32 +void CALL32( s32 to ); +// call r32 +void CALL32R( x86IntRegType to ); +// call m32 +void CALL64R( x86IntRegType to ); + + +//////////////////////////////////// +// misc instructions // +//////////////////////////////////// + +// cmp imm32 to r64 +void CMP64I32toR( x86IntRegType to, u32 from ); +// cmp m64 to r64 +void CMP64MtoR( x86IntRegType to, uptr from ); +// cmp r64 to r64 +void CMP64RtoR( x86IntRegType to, x86IntRegType from ); + +// cmp imm32 to r32 +void CMP32ItoR( x86IntRegType to, u32 from ); +// cmp imm32 to m32 +void CMP32ItoM( uptr to, u32 from ); +// cmp r32 to r32 +void CMP32RtoR( x86IntRegType to, x86IntRegType from ); +// cmp m32 to r32 +void CMP32MtoR( x86IntRegType to, uptr from ); +// cmp imm32 to [r32] +void CMP32I8toRm( x86IntRegType to, u8 from); +// cmp imm32 to [r32+off] +void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off); +// cmp imm8 to [r32] +void CMP32I8toM( uptr to, u8 from); + +// cmp imm16 to r16 +void CMP16ItoR( x86IntRegType to, u16 from ); +// cmp imm16 to m16 +void CMP16ItoM( uptr to, u16 from ); +// cmp r16 to r16 +void CMP16RtoR( x86IntRegType to, x86IntRegType from ); +// cmp m16 to r16 +void CMP16MtoR( x86IntRegType to, uptr from ); + +// cmp imm8 to r8 +void CMP8ItoR( x86IntRegType to, u8 from ); +// cmp m8 to r8 +void CMP8MtoR( x86IntRegType to, uptr from ); + +// test r64 to r64 +void TEST64RtoR( x86IntRegType to, x86IntRegType from ); +// test imm32 to r32 +void TEST32ItoR( x86IntRegType to, u32 from ); +// test imm32 to m32 +void TEST32ItoM( uptr to, u32 from ); +// test r32 to r32 +void TEST32RtoR( x86IntRegType to, x86IntRegType from ); +// test imm32 to [r32] +void TEST32ItoRm( x86IntRegType to, u32 from ); +// test imm16 to r16 +void TEST16ItoR( x86IntRegType to, u16 from ); +// test r16 to r16 +void TEST16RtoR( x86IntRegType to, x86IntRegType from ); +// test imm8 to r8 +void TEST8ItoR( x86IntRegType to, u8 from ); +// test imm8 to r8 +void TEST8ItoM( uptr to, u8 from ); + +// sets r8 +void SETS8R( x86IntRegType to ); +// setl r8 +void SETL8R( x86IntRegType to ); +// setge r8 +void SETGE8R( x86IntRegType to ); +// setge r8 +void SETG8R( x86IntRegType to ); +// seta r8 +void SETA8R( x86IntRegType to ); +// setae r8 +void SETAE8R( x86IntRegType to ); +// setb r8 +void SETB8R( x86IntRegType to ); +// setnz r8 +void SETNZ8R( x86IntRegType to ); +// setz r8 +void SETZ8R( x86IntRegType to ); +// sete r8 +void SETE8R( x86IntRegType to ); + +// push imm32 +void PUSH32I( u32 from ); + +#ifdef __x86_64__ +void PUSHI( u32 from ); +// push r64 +void PUSH64R( x86IntRegType from ); +// push m64 +void PUSH64M( uptr from ); +// pop r32 +void POP64R( x86IntRegType from ); +#else +// push r32 +void PUSH32R( x86IntRegType from ); +// push m32 +void PUSH32M( u32 from ); +// push imm32 +void PUSH32I( u32 from ); +// pop r32 +void POP32R( x86IntRegType from ); +// pushad +void PUSHA32( void ); +// popad +void POPA32( void ); +#endif + +void PUSHR(x86IntRegType from); +void POPR(x86IntRegType from); + +// pushfd +void PUSHFD( void ); +// popfd +void POPFD( void ); +// ret +void RET( void ); +// ret (2-byte code used for misprediction) +void RET2( void ); + +void CBW(); +void CWDE(); +// cwd +void CWD( void ); +// cdq +void CDQ( void ); +// cdqe +void CDQE( void ); + +void LAHF(); +void SAHF(); + +void BT32ItoR( x86IntRegType to, x86IntRegType from ); +void BSRRtoR(x86IntRegType to, x86IntRegType from); +void BSWAP32R( x86IntRegType to ); + +// to = from + offset +void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset); +void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset); + +// to = from0 + from1 +void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1); +void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1); + +// to = from << scale (max is 3) +void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale); +void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale); + +//****************** +// FPU instructions +//****************** + +// fild m32 to fpu reg stack +void FILD32( uptr from ); +// fistp m32 from fpu reg stack +void FISTP32( uptr from ); +// fld m32 to fpu reg stack +void FLD32( uptr from ); +// fld st(i) +void FLD(int st); +// fld1 (push +1.0f on the stack) +void FLD1(); +// fld1 (push log_2 e on the stack) +void FLDL2E(); +// fst m32 from fpu reg stack +void FST32( uptr to ); +// fstp m32 from fpu reg stack +void FSTP32( uptr to ); +// fstp st(i) +void FSTP(int st); + +// fldcw fpu control word from m16 +void FLDCW( uptr from ); +// fstcw fpu control word to m16 +void FNSTCW( uptr to ); +void FXAM(); +void FDECSTP(); +// frndint +void FRNDINT(); +void FXCH(int st); +void F2XM1(); +void FSCALE(); + +// fadd ST(src) to fpu reg stack ST(0) +void FADD32Rto0( x86IntRegType src ); +// fadd ST(0) to fpu reg stack ST(src) +void FADD320toR( x86IntRegType src ); +// fsub ST(src) to fpu reg stack ST(0) +void FSUB32Rto0( x86IntRegType src ); +// fsub ST(0) to fpu reg stack ST(src) +void FSUB320toR( x86IntRegType src ); +// fsubp -> 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( uptr from ); +// fsub m32 to fpu reg stack +void FSUB32( uptr from ); +// fmul m32 to fpu reg stack +void FMUL32( uptr from ); +// fdiv m32 to fpu reg stack +void FDIV32( uptr 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( uptr 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( uptr from ); +void FNSTSWtoAX( void ); + +// probably a little extreme here, but x86-64 should NOT use MMX +#ifdef __x86_64__ + +#define MMXONLY(code) + +#else + +#define MMXONLY(code) code + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +void MOVQMtoR( x86MMXRegType to, uptr from ); +// movq r64 to m64 +void MOVQRtoM( uptr 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, uptr from ); +// pandn r64 to r64 +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +void PANDNMtoR( x86MMXRegType to, uptr from ); +// por r64 to r64 +void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +void PORMtoR( x86MMXRegType to, uptr from ); +// pxor r64 to r64 +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +void PXORMtoR( x86MMXRegType to, uptr from ); + +// psllq r64 to r64 +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +void PSLLQMtoR( x86MMXRegType to, uptr 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, uptr 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, uptr from ); +// paddusw r64 to r64 +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +void PADDUSWMtoR( x86MMXRegType to, uptr from ); + +// paddb r64 to r64 +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +void PADDBMtoR( x86MMXRegType to, uptr from ); +// paddw r64 to r64 +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +void PADDWMtoR( x86MMXRegType to, uptr from ); +// paddd r64 to r64 +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +void PADDDMtoR( x86MMXRegType to, uptr from ); +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, uptr 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, uptr from ); + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, uptr from ); +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ); + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, uptr 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, uptr from ); +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDMtoR( x86MMXRegType to, uptr 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, uptr from ); +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKHDQMtoR( x86MMXRegType to, uptr 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, uptr from ); +void MOVDMMXtoM( uptr 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, uptr 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); + +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +#endif // !__x86_64__ + +//********************* +// SSE instructions * +//********************* +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ); +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ); + +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr 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, int offset ); +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ); + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from ); +void SSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from ); +void SSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int 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, int offset ); +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int 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, int offset ); +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ); + +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ); +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); + +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, uptr from ); + +void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_XORPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +#ifndef __x86_64__ +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ); +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ); +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ); +#endif +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from); +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from); +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from); + +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from, u8 imm8 ); +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ); +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, uptr 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, uptr from, u8 imm8 ); + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); + +void SSE_STMXCSR( uptr from ); +void SSE_LDMXCSR( uptr from ); + + +//********************* +// SSE 2 Instructions* +//********************* +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from); +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_MOVDQU_XMM_to_M128( uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from ); +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PAND_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from); +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr from); + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from); + +// mult by half words +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from ); +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ); +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from ); +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr 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, int 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, int offset ); + +#ifdef __x86_64__ +void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from ); +#endif + +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr from ); + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from); +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr 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, uptr from ); +void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ); +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from ); +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr 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, int offset ); +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr 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, uptr from); +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from); + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +//********************* +// 3DNOW instructions * +//********************* +void FEMMS( void ); +void PFCMPEQMtoR( x86IntRegType to, uptr from ); +void PFCMPGTMtoR( x86IntRegType to, uptr from ); +void PFCMPGEMtoR( x86IntRegType to, uptr from ); +void PFADDMtoR( x86IntRegType to, uptr from ); +void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +void PFSUBMtoR( x86IntRegType to, uptr from ); +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +void PFMULMtoR( x86IntRegType to, uptr from ); +void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPMtoR( x86IntRegType to, uptr 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, uptr from ); +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ); +void PI2FDMtoR( x86IntRegType to, uptr from ); +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +void PFMAXMtoR( x86IntRegType to, uptr from ); +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +void PFMINMtoR( x86IntRegType to, uptr 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, uptr from); +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, int offset ); + +#ifndef __x86_64__ +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); +#endif + +/* 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, uptr from ); +void SSE2EMU_MOVD_XMM_to_M32( uptr to, x86SSERegType from ); +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); + +//////////////////////////////////////////////////// +#ifdef _DEBUG +#define WRITECHECK() CheckX86Ptr() +#else +#define WRITECHECK() +#endif + +#define writeVAL(val) ({ \ + WRITECHECK(); \ + *(typeof(val)*)x86Ptr = (val); \ + x86Ptr += sizeof(val); \ + (void)0; \ + }) + +#define write8(val ) writeVAL((u8)(val)) +#define write16(val ) writeVAL((u16)(val)) +#define write32( val ) writeVAL((u32)(val)) +#define write64( val ) writeVAL((u64)(val)) + +#ifdef __cplusplus +} +#endif + +#endif // __IX86_H__ diff --git a/libpcsxcore/ix86_64/ix86_cpudetect.c b/libpcsxcore/ix86_64/ix86_cpudetect.c index 6bf0bb5b..c59186bf 100644..100755 --- a/libpcsxcore/ix86_64/ix86_cpudetect.c +++ b/libpcsxcore/ix86_64/ix86_cpudetect.c @@ -1,492 +1,492 @@ -/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifdef __x86_64__
-
-#if defined (_WIN32)
-#include <windows.h>
-#endif
-
-#include <string.h>
-#include <stdio.h>
-
-#include "ix86-64.h"
-
-#if defined (_MSC_VER) && _MSC_VER >= 1400
-
- void __cpuid(int* CPUInfo, int InfoType);
- unsigned __int64 __rdtsc();
-
- #pragma intrinsic(__cpuid)
- #pragma intrinsic(__rdtsc)
-
-#endif
-
-CAPABILITIES cpucaps;
-CPUINFO cpuinfo;
-
-#define cpuid(cmd,a,b,c,d) \
- __asm__ __volatile__("cpuid" \
- : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "0" (cmd))
-
-static s32 iCpuId( u32 cmd, u32 *regs )
-{
- int flag=1;
-
-#if defined (_MSC_VER) && _MSC_VER >= 1400
-
- __cpuid( regs, cmd );
-
- return 0;
-
-#elif defined (_MSC_VER)
-
-#ifdef __x86_64__
- assert(0);
-#else // __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;
- }
-#endif // __x86_64__
- return 0;
-
-
-#else
-
-#ifndef __x86_64__
- // see if we can use cpuid
- __asm__ __volatile__ (
- "sub $0x18, %%esp\n"
- "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"
- "add $0x18, %%esp\n"
- : "=r"(flag) :
- );
-#endif
-
- if ( !flag )
- return -1;
-
- cpuid(cmd, regs[0], regs[1], regs[2], regs[3]);
- return 0;
-#endif // _MSC_VER
-}
-
-u64 GetCPUTick( void )
-{
-#if defined (_MSC_VER) && _MSC_VER >= 1400
-
- 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__) || defined(__APPLE__)
-
-#include <sys/time.h>
-#include <errno.h>
-//*
-unsigned long timeGetTime2()
-{
- struct timeval tv;
- gettimeofday(&tv, 0); // well, maybe there are better ways
- return (unsigned long)tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works
-}
-//*/
-#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 = timeGetTime2( );
- while( timeGetTime2( ) == timeStart )
- {
- timeStart = timeGetTime2( );
- }
- for(;;)
- {
- timeStop = timeGetTime2( );
- if ( ( timeStop - timeStart ) > 1 )
- {
- startTick = GetCPUTick( );
- break;
- }
- }
-
- timeStart = timeStop;
- for(;;)
- {
- timeStop = timeGetTime2( );
- 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 = 0;
- u32 x86_64_12BITBRANDID = 0;
- 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;
- case 15: // Core 2 Duo Allendale/Conroe
- strcpy( cpuinfo.x86Fam, "Intel Core 2 Duo" );
- 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;
- case 5:
- strcpy( cpuinfo.x86Fam, "AMD Athlon X2 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 44:
- strcpy( cpuinfo.x86Fam, "AMD Opteron(tm) Dual Core 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+ Processor" );
- }
- }
- else
- {
- switch ( cpuinfo.x86Family )
- {
- case 4:
- switch( cpuinfo.x86Model )
- {
- case 14:
- case 15: // Write-back enhanced
- strcpy( cpuinfo.x86Fam, "AMD 5x86 Processor" );
- break;
-
- case 3: // DX2
- case 7: // Write-back enhanced DX2
- case 8: // DX4
- case 9: // Write-back enhanced DX4
- strcpy( cpuinfo.x86Fam, "AMD 486 Processor" );
- break;
-
-
- default:
- strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" );
-
- }
- 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 Processor" );
- 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 Series Processor" );
- break;
-
- default:
- strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" );
- }
- break;
- case 6:
- strcpy( cpuinfo.x86Fam, "AMD Athlon XP Processor" );
- 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);
-}
-
-#endif
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef __x86_64__ + +#if defined (_WIN32) +#include <windows.h> +#endif + +#include <string.h> +#include <stdio.h> + +#include "ix86-64.h" + +#if defined (_MSC_VER) && _MSC_VER >= 1400 + + void __cpuid(int* CPUInfo, int InfoType); + unsigned __int64 __rdtsc(); + + #pragma intrinsic(__cpuid) + #pragma intrinsic(__rdtsc) + +#endif + +CAPABILITIES cpucaps; +CPUINFO cpuinfo; + +#define cpuid(cmd,a,b,c,d) \ + __asm__ __volatile__("cpuid" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "0" (cmd)) + +static s32 iCpuId( u32 cmd, u32 *regs ) +{ + int flag=1; + +#if defined (_MSC_VER) && _MSC_VER >= 1400 + + __cpuid( regs, cmd ); + + return 0; + +#elif defined (_MSC_VER) + +#ifdef __x86_64__ + assert(0); +#else // __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; + } +#endif // __x86_64__ + return 0; + + +#else + +#ifndef __x86_64__ + // see if we can use cpuid + __asm__ __volatile__ ( + "sub $0x18, %%esp\n" + "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" + "add $0x18, %%esp\n" + : "=r"(flag) : + ); +#endif + + if ( !flag ) + return -1; + + cpuid(cmd, regs[0], regs[1], regs[2], regs[3]); + return 0; +#endif // _MSC_VER +} + +u64 GetCPUTick( void ) +{ +#if defined (_MSC_VER) && _MSC_VER >= 1400 + + 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__) || defined(__APPLE__) + +#include <sys/time.h> +#include <errno.h> +//* +unsigned long timeGetTime2() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return (unsigned long)tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works +} +//*/ +#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 = timeGetTime2( ); + while( timeGetTime2( ) == timeStart ) + { + timeStart = timeGetTime2( ); + } + for(;;) + { + timeStop = timeGetTime2( ); + if ( ( timeStop - timeStart ) > 1 ) + { + startTick = GetCPUTick( ); + break; + } + } + + timeStart = timeStop; + for(;;) + { + timeStop = timeGetTime2( ); + 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 = 0; + u32 x86_64_12BITBRANDID = 0; + 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; + case 15: // Core 2 Duo Allendale/Conroe + strcpy( cpuinfo.x86Fam, "Intel Core 2 Duo" ); + 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; + case 5: + strcpy( cpuinfo.x86Fam, "AMD Athlon X2 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 44: + strcpy( cpuinfo.x86Fam, "AMD Opteron(tm) Dual Core 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+ Processor" ); + } + } + else + { + switch ( cpuinfo.x86Family ) + { + case 4: + switch( cpuinfo.x86Model ) + { + case 14: + case 15: // Write-back enhanced + strcpy( cpuinfo.x86Fam, "AMD 5x86 Processor" ); + break; + + case 3: // DX2 + case 7: // Write-back enhanced DX2 + case 8: // DX4 + case 9: // Write-back enhanced DX4 + strcpy( cpuinfo.x86Fam, "AMD 486 Processor" ); + break; + + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" ); + + } + 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 Processor" ); + 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 Series Processor" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" ); + } + break; + case 6: + strcpy( cpuinfo.x86Fam, "AMD Athlon XP Processor" ); + 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); +} + +#endif diff --git a/libpcsxcore/ix86_64/ix86_mmx.c b/libpcsxcore/ix86_64/ix86_mmx.c index 549a681e..09784a9c 100644..100755 --- a/libpcsxcore/ix86_64/ix86_mmx.c +++ b/libpcsxcore/ix86_64/ix86_mmx.c @@ -1,651 +1,651 @@ -// stop compiling if NORECBUILD build (only for Visual Studio)
-
-#ifdef __x86_64__
-
-#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
-
-#include "ix86-64.h"
-
-#include <assert.h>
-
-/********************/
-/* MMX instructions */
-/********************/
-
-// r64 = mm
-
-/* movq m64 to r64 */
-void MOVQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x6F), true, to, from, 0);
-}
-
-/* movq r64 to m64 */
-void MOVQRtoM( uptr to, x86MMXRegType from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x7F), true, from, to, 0);
-}
-
-/* pand r64 to r64 */
-void PANDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xDB0F );
- ModRM( 3, to, from );
-}
-
-void PANDNRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xDF0F );
- ModRM( 3, to, from );
-}
-
-/* por r64 to r64 */
-void PORRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xEB0F );
- ModRM( 3, to, from );
-}
-
-/* pxor r64 to r64 */
-void PXORRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xEF0F );
- ModRM( 3, to, from );
-}
-
-/* psllq r64 to r64 */
-void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xF30F );
- ModRM( 3, to, from );
-}
-
-/* psllq m64 to r64 */
-void PSLLQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xF3), true, to, from, 0);
-}
-
-/* psllq imm8 to r64 */
-void PSLLQItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x730F );
- ModRM( 3, 6, to);
- write8( from );
-}
-
-/* psrlq r64 to r64 */
-void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xD30F );
- ModRM( 3, to, from );
-}
-
-/* psrlq m64 to r64 */
-void PSRLQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xD3), true, to, from, 0);
-}
-
-/* psrlq imm8 to r64 */
-void PSRLQItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x730F );
- ModRM( 3, 2, to);
- write8( from );
-}
-
-/* paddusb r64 to r64 */
-void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xDC0F );
- ModRM( 3, to, from );
-}
-
-/* paddusb m64 to r64 */
-void PADDUSBMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xDC), true, to, from, 0);
-}
-
-/* paddusw r64 to r64 */
-void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xDD0F );
- ModRM( 3, to, from );
-}
-
-/* paddusw m64 to r64 */
-void PADDUSWMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xDD), true, to, from, 0);
-}
-
-/* paddb r64 to r64 */
-void PADDBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xFC0F );
- ModRM( 3, to, from );
-}
-
-/* paddb m64 to r64 */
-void PADDBMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xFC), true, to, from, 0);
-}
-
-/* paddw r64 to r64 */
-void PADDWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xFD0F );
- ModRM( 3, to, from );
-}
-
-/* paddw m64 to r64 */
-void PADDWMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xFD), true, to, from, 0);
-}
-
-/* paddd r64 to r64 */
-void PADDDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xFE0F );
- ModRM( 3, to, from );
-}
-
-/* paddd m64 to r64 */
-void PADDDMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xFE), true, to, from, 0);
-}
-
-/* emms */
-void EMMS( void )
-{
- write16( 0x770F );
-}
-
-void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xEC0F );
- ModRM( 3, to, from );
-}
-
-void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xED0F );
- ModRM( 3, to, from );
-}
-
-// paddq m64 to r64 (sse2 only?)
-void PADDQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xD4), true, to, from, 0);
-}
-
-// paddq r64 to r64 (sse2 only?)
-void PADDQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xD40F );
- ModRM( 3, to, from );
-}
-
-void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xE80F );
- ModRM( 3, to, from );
-}
-
-void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xE90F );
- ModRM( 3, to, from );
-}
-
-
-void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xF80F );
- ModRM( 3, to, from );
-}
-
-void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xF90F );
- ModRM( 3, to, from );
-}
-
-void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xFA0F );
- ModRM( 3, to, from );
-}
-
-void PSUBDMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xFA), true, to, from, 0);
-}
-
-void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xD80F );
- ModRM( 3, to, from );
-}
-
-void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xD90F );
- ModRM( 3, to, from );
-}
-
-// psubq m64 to r64 (sse2 only?)
-void PSUBQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xFB), true, to, from, 0);
-}
-
-// psubq r64 to r64 (sse2 only?)
-void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xFB0F );
- ModRM( 3, to, from );
-}
-
-// pmuludq m64 to r64 (sse2 only?)
-void PMULUDQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xF4), true, to, from, 0);
-}
-
-// pmuludq r64 to r64 (sse2 only?)
-void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xF40F );
- ModRM( 3, to, from );
-}
-
-void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x740F );
- ModRM( 3, to, from );
-}
-
-void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x750F );
- ModRM( 3, to, from );
-}
-
-void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x760F );
- ModRM( 3, to, from );
-}
-
-void PCMPEQDMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x76), true, to, from, 0);
-}
-
-void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x640F );
- ModRM( 3, to, from );
-}
-
-void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x650F );
- ModRM( 3, to, from );
-}
-
-void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x660F );
- ModRM( 3, to, from );
-}
-
-void PCMPGTDMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x66), true, to, from, 0);
-}
-
-void PSRLWItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x710F );
- ModRM( 3, 2 , to );
- write8( from );
-}
-
-void PSRLDItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x720F );
- ModRM( 3, 2 , to );
- write8( from );
-}
-
-void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xD20F );
- ModRM( 3, to, from );
-}
-
-void PSLLWItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x710F );
- ModRM( 3, 6 , to );
- write8( from );
-}
-
-void PSLLDItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x720F );
- ModRM( 3, 6 , to );
- write8( from );
-}
-
-void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xF20F );
- ModRM( 3, to, from );
-}
-
-void PSRAWItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x710F );
- ModRM( 3, 4 , to );
- write8( from );
-}
-
-void PSRADItoR( x86MMXRegType to, u8 from )
-{
- RexB(0, to);
- write16( 0x720F );
- ModRM( 3, 4 , to );
- write8( from );
-}
-
-void PSRADRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0xE20F );
- ModRM( 3, to, from );
-}
-
-/* por m64 to r64 */
-void PORMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xEB), true, to, from, 0);
-}
-
-/* pxor m64 to r64 */
-void PXORMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xEF), true, to, from, 0);
-}
-
-/* pand m64 to r64 */
-void PANDMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xDB), true, to, from, 0);
-}
-
-void PANDNMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0xDF), true, to, from, 0);
-}
-
-void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x6A0F );
- ModRM( 3, to, from );
-}
-
-void PUNPCKHDQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x6A), true, to, from, 0);
-}
-
-void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x620F );
- ModRM( 3, to, from );
-}
-
-void PUNPCKLDQMtoR( x86MMXRegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x62), true, to, from, 0);
-}
-
-void MOVQ64ItoR( x86MMXRegType reg, u64 i )
-{
- RexR(0, reg);
- write16(0x6F0F);
- ModRM(0, reg, DISP32);
- write32(2);
- JMP8( 8 );
- write64( i );
-}
-
-void MOVQRtoR( x86MMXRegType to, x86MMXRegType from )
-{
- RexRB(0, to, from);
- write16( 0x6F0F );
- ModRM( 3, to, from );
-}
-
-void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset )
-{
- RexRB(0, to, from);
- 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 )
-{
- RexRB(0, from, to);
- 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, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x6E), true, to, from, 0);
-}
-
-/* movd r64 to m32 */
-void MOVDMMXtoM( uptr to, x86MMXRegType from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x7E), true, from, to, 0);
-}
-
-void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from )
-{
- RexRB(0, to, from);
- write16( 0x6E0F );
- ModRM( 3, to, from );
-}
-
-void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from )
-{
- RexRB(0, to, from);
- write16( 0x6E0F );
- ModRM( 0, to, from );
-}
-
-void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset )
-{
- RexRB(0, to, from);
- write16( 0x6E0F );
-
- if( offset < 128 ) {
- ModRM( 1, to, from );
- write8(offset);
- }
- else {
- ModRM( 2, to, from );
- write32(offset);
- }
-}
-
-void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from )
-{
- RexRB(0, from, to);
- write16( 0x7E0F );
- ModRM( 3, from, to );
-}
-
-void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from )
-{
- RexRB(0, from, to);
- 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 )
-{
- RexRB(0, from, to);
- 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)
-{
- RexRB(0, to, from);
- write16( 0x630F );
- ModRM( 3, to, from );
-}
-
-void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from)
-{
- RexRB(0, to, from);
- write16( 0x6B0F );
- ModRM( 3, to, from );
-}
-
-void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from)
-{
- RexRB(0, to, from);
- write16( 0xD70F );
- ModRM( 3, to, from );
-}
-
-void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 )
-{
- RexRB(0, to, from);
- write16( 0xc40f );
- ModRM( 3, to, from );
- write8( imm8 );
-}
-
-void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8)
-{
- RexRB(0, to, from);
- write16(0x700f);
- ModRM( 3, to, from );
- write8(imm8);
-}
-
-void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8)
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x70), true, to, from, 1 /* XXX was 0? */);
- write8(imm8);
-}
-
-void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from)
-{
- RexRB(0, to, from);
- write16(0xf70f);
- ModRM( 3, to, from );
-}
-
-#endif
-
-#endif
+// stop compiling if NORECBUILD build (only for Visual Studio) + +#ifdef __x86_64__ + +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "ix86-64.h" + +#include <assert.h> + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x6F), true, to, from, 0); +} + +/* movq r64 to m64 */ +void MOVQRtoM( uptr to, x86MMXRegType from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x7F), true, from, to, 0); +} + +/* pand r64 to r64 */ +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xDB0F ); + ModRM( 3, to, from ); +} + +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xDF0F ); + ModRM( 3, to, from ); +} + +/* por r64 to r64 */ +void PORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xEB0F ); + ModRM( 3, to, from ); +} + +/* pxor r64 to r64 */ +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xEF0F ); + ModRM( 3, to, from ); +} + +/* psllq r64 to r64 */ +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xF30F ); + ModRM( 3, to, from ); +} + +/* psllq m64 to r64 */ +void PSLLQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xF3), true, to, from, 0); +} + +/* psllq imm8 to r64 */ +void PSLLQItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 6, to); + write8( from ); +} + +/* psrlq r64 to r64 */ +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xD30F ); + ModRM( 3, to, from ); +} + +/* psrlq m64 to r64 */ +void PSRLQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xD3), true, to, from, 0); +} + +/* psrlq imm8 to r64 */ +void PSRLQItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 2, to); + write8( from ); +} + +/* paddusb r64 to r64 */ +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xDC0F ); + ModRM( 3, to, from ); +} + +/* paddusb m64 to r64 */ +void PADDUSBMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xDC), true, to, from, 0); +} + +/* paddusw r64 to r64 */ +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xDD0F ); + ModRM( 3, to, from ); +} + +/* paddusw m64 to r64 */ +void PADDUSWMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xDD), true, to, from, 0); +} + +/* paddb r64 to r64 */ +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xFC0F ); + ModRM( 3, to, from ); +} + +/* paddb m64 to r64 */ +void PADDBMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xFC), true, to, from, 0); +} + +/* paddw r64 to r64 */ +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xFD0F ); + ModRM( 3, to, from ); +} + +/* paddw m64 to r64 */ +void PADDWMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xFD), true, to, from, 0); +} + +/* paddd r64 to r64 */ +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xFE0F ); + ModRM( 3, to, from ); +} + +/* paddd m64 to r64 */ +void PADDDMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xFE), true, to, from, 0); +} + +/* emms */ +void EMMS( void ) +{ + write16( 0x770F ); +} + +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xEC0F ); + ModRM( 3, to, from ); +} + +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xED0F ); + ModRM( 3, to, from ); +} + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xD4), true, to, from, 0); +} + +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xD40F ); + ModRM( 3, to, from ); +} + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xE80F ); + ModRM( 3, to, from ); +} + +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xE90F ); + ModRM( 3, to, from ); +} + + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xF80F ); + ModRM( 3, to, from ); +} + +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xF90F ); + ModRM( 3, to, from ); +} + +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xFA0F ); + ModRM( 3, to, from ); +} + +void PSUBDMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xFA), true, to, from, 0); +} + +void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xD80F ); + ModRM( 3, to, from ); +} + +void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xD90F ); + ModRM( 3, to, from ); +} + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xFB), true, to, from, 0); +} + +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xFB0F ); + ModRM( 3, to, from ); +} + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xF4), true, to, from, 0); +} + +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xF40F ); + ModRM( 3, to, from ); +} + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x740F ); + ModRM( 3, to, from ); +} + +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x750F ); + ModRM( 3, to, from ); +} + +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x760F ); + ModRM( 3, to, from ); +} + +void PCMPEQDMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x76), true, to, from, 0); +} + +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x640F ); + ModRM( 3, to, from ); +} + +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x650F ); + ModRM( 3, to, from ); +} + +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x660F ); + ModRM( 3, to, from ); +} + +void PCMPGTDMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x66), true, to, from, 0); +} + +void PSRLWItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xD20F ); + ModRM( 3, to, from ); +} + +void PSLLWItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xF20F ); + ModRM( 3, to, from ); +} + +void PSRAWItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADItoR( x86MMXRegType to, u8 from ) +{ + RexB(0, to); + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0xE20F ); + ModRM( 3, to, from ); +} + +/* por m64 to r64 */ +void PORMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xEB), true, to, from, 0); +} + +/* pxor m64 to r64 */ +void PXORMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xEF), true, to, from, 0); +} + +/* pand m64 to r64 */ +void PANDMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xDB), true, to, from, 0); +} + +void PANDNMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0xDF), true, to, from, 0); +} + +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x6A0F ); + ModRM( 3, to, from ); +} + +void PUNPCKHDQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x6A), true, to, from, 0); +} + +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x620F ); + ModRM( 3, to, from ); +} + +void PUNPCKLDQMtoR( x86MMXRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x62), true, to, from, 0); +} + +void MOVQ64ItoR( x86MMXRegType reg, u64 i ) +{ + RexR(0, reg); + write16(0x6F0F); + ModRM(0, reg, DISP32); + write32(2); + JMP8( 8 ); + write64( i ); +} + +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + RexRB(0, to, from); + write16( 0x6F0F ); + ModRM( 3, to, from ); +} + +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + RexRB(0, to, from); + 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 ) +{ + RexRB(0, from, to); + 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, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x6E), true, to, from, 0); +} + +/* movd r64 to m32 */ +void MOVDMMXtoM( uptr to, x86MMXRegType from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x7E), true, from, to, 0); +} + +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x6E0F ); + ModRM( 3, to, from ); +} + +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x6E0F ); + ModRM( 0, to, from ); +} + +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + RexRB(0, to, from); + write16( 0x6E0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) +{ + RexRB(0, from, to); + write16( 0x7E0F ); + ModRM( 3, from, to ); +} + +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ) +{ + RexRB(0, from, to); + 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 ) +{ + RexRB(0, from, to); + 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) +{ + RexRB(0, to, from); + write16( 0x630F ); + ModRM( 3, to, from ); +} + +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + RexRB(0, to, from); + write16( 0x6B0F ); + ModRM( 3, to, from ); +} + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) +{ + RexRB(0, to, from); + write16( 0xD70F ); + ModRM( 3, to, from ); +} + +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) +{ + RexRB(0, to, from); + write16( 0xc40f ); + ModRM( 3, to, from ); + write8( imm8 ); +} + +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) +{ + RexRB(0, to, from); + write16(0x700f); + ModRM( 3, to, from ); + write8(imm8); +} + +void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x70), true, to, from, 1 /* XXX was 0? */); + write8(imm8); +} + +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) +{ + RexRB(0, to, from); + write16(0xf70f); + ModRM( 3, to, from ); +} + +#endif + +#endif diff --git a/libpcsxcore/ix86_64/ix86_sse.c b/libpcsxcore/ix86_64/ix86_sse.c index 30f8060b..8a4f0217 100644..100755 --- a/libpcsxcore/ix86_64/ix86_sse.c +++ b/libpcsxcore/ix86_64/ix86_sse.c @@ -1,1460 +1,1460 @@ -// stop compiling if NORECBUILD build (only for Visual Studio)
-
-#ifdef __x86_64__
-
-#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
-
-#include <assert.h>
-#include "ix86-64.h"
-
-PCSX2_ALIGNED16(static unsigned int p[4]);
-PCSX2_ALIGNED16(static unsigned int p2[4]);
-PCSX2_ALIGNED16(static float f[4]);
-
-
-XMMSSEType g_xmmtypes[XMMREGS] = {0};
-
-/********************/
-/* SSE instructions */
-/********************/
-
-#define SSEMtoRv( nc, code, overb ) \
- assert( cpucaps.hasStreamingSIMDExtensions ); \
- assert( to < XMMREGS ) ; \
- MEMADDR_OP(0, nc, code, true, to, from, overb)
-
-#define SSEMtoR( code, overb ) SSEMtoRv(2, code, overb)
-
-#define SSERtoMv( nc, code, overb ) \
- assert( cpucaps.hasStreamingSIMDExtensions ); \
- assert( from < XMMREGS) ; \
- MEMADDR_OP(0, nc, code, true, from, to, overb)
-
-#define SSERtoM( code, overb ) SSERtoMv( 2, code, overb ) \
-
-#define SSE_SS_MtoR( code, overb ) \
- SSEMtoRv(3, (code << 8) | 0xF3, overb)
-
-#define SSE_SS_RtoM( code, overb ) \
- SSERtoMv(3, (code << 8) | 0xF3, overb)
-
-#define SSERtoR( code ) \
- assert( cpucaps.hasStreamingSIMDExtensions ); \
- assert( to < XMMREGS && from < XMMREGS) ; \
- RexRB(0, to, from); \
- write16( code ); \
- ModRM( 3, to, from );
-
-#define SSEMtoR66( code ) \
- SSEMtoRv( 3, (code << 8) | 0x66, 0 )
-
-#define SSERtoM66( code ) \
- SSERtoMv( 3, (code << 8) | 0x66, 0 )
-
-#define SSERtoR66( code ) \
- write8( 0x66 ); \
- SSERtoR( code );
-
-#define _SSERtoR66( code ) \
- assert( cpucaps.hasStreamingSIMDExtensions ); \
- assert( to < XMMREGS && from < XMMREGS) ; \
- write8( 0x66 ); \
- RexRB(0, from, to); \
- write16( code ); \
- ModRM( 3, from, to );
-
-#define SSE_SS_RtoR( code ) \
- assert( cpucaps.hasStreamingSIMDExtensions ); \
- assert( to < XMMREGS && from < XMMREGS) ; \
- write8( 0xf3 ); \
- RexRB(0, to, from); \
- 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 );
-
-
-
-void WriteRmOffset(x86IntRegType to, int offset);
-void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset);
-
-/* movups [r32][r32*scale] to xmm1 */
-void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRXB(0, to, from2, from);
- 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 )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRXB(1, to, from2, from);
- write16( 0x110f );
- ModRM( 0, to, 0x4 );
- SibSB( scale, from2, from );
-}
-
-/* movups [r32] to r32 */
-void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, to, from);
- write16( 0x100f );
- ModRM( 0, to, from );
-}
-
-/* movups r32 to [r32] */
-void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, from, to);
- write16( 0x110f );
- ModRM( 0, from, to );
-}
-
-/* movlps [r32] to r32 */
-void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(1, to, from);
- write16( 0x120f );
- ModRM( 0, to, from );
-}
-
-void SSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, to, from);
- write16( 0x120f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-/* movaps r32 to [r32] */
-void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, from, to);
- write16( 0x130f );
- ModRM( 0, from, to );
-}
-
-void SSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, from, to);
- write16( 0x130f );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-/* movaps [r32][r32*scale] to xmm1 */
-void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
-{
- assert( cpucaps.hasStreamingSIMDExtensions && from != EBP );
- RexRXB(0, to, from2, from);
- write16( 0x280f );
- 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 )
-{
- assert( cpucaps.hasStreamingSIMDExtensions && from != EBP );
- RexRXB(0, to, from2, from);
- write16( 0x290f );
- ModRM( 0, to, 0x4 );
- SibSB( scale, from2, from );
-}
-
-// movaps [r32+offset] to r32
-void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, to, from);
- write16( 0x280f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-// movaps r32 to [r32+offset]
-void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, from, to);
- write16( 0x290f );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-// movdqa [r32+offset] to r32
-void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- write8(0x66);
- RexRB(0, to, from);
- write16( 0x6f0f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-// movdqa r32 to [r32+offset]
-void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- write8(0x66);
- RexRB(0, from, to);
- write16( 0x7f0f );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-// movups [r32+offset] to r32
-void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
-{
- RexRB(0, to, from);
- write16( 0x100f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-// movups r32 to [r32+offset]
-void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, from, to);
- write16( 0x110f );
- WriteRmOffsetFrom(from, to, offset);
-}
-
-//**********************************************************************************/
-//MOVAPS: Move aligned Packed Single Precision FP values *
-//**********************************************************************************
-void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); }
-void SSE_MOVAPS_XMM_to_M128( uptr 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, uptr from ) { SSEMtoR( 0x100f, 0 ); }
-void SSE_MOVUPS_XMM_to_M128( uptr 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, uptr from )
-{
- if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_M64_to_XMM(to, from);
- else {
- SSE_SS_MtoR( 0x7e0f, 0);
- }
-}
-
-void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from )
-{
- if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_XMM_to_XMM(to, from);
- else {
- SSE_SS_RtoR( 0x7e0f);
- }
-}
-
-void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from )
-{
- if( !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVLPS_XMM_to_M64(to, from);
- else {
- SSERtoM66(0xd60f);
- }
-}
-
-#ifndef __x86_64__
-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 {
- SSE_SS_RtoR( 0xd60f);
- }
-}
-#endif
-
-//**********************************************************************************/
-//MOVSS: Move Scalar Single-Precision FP value *
-//**********************************************************************************
-void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr 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);
- RexRB(0, from, to);
- 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, int offset )
-{
- write8(0xf3);
- RexRB(0, to, from);
- write16( 0x100f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
-{
- write8(0xf3);
- RexRB(0, from, to);
- write16(0x110f);
- WriteRmOffsetFrom(from, to, 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, uptr 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, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, to, from);
- write16( 0x120f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
-{
- RexRB(0, from, to);
- write16(0x130f);
- WriteRmOffsetFrom(from, to, offset);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//MOVHPS: Move High Packed Single-Precision FP *
-//**********************************************************************************
-void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr 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, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, to, from);
- write16( 0x160f );
- WriteRmOffsetFrom(to, from, offset);
-}
-
-void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
-{
- assert( cpucaps.hasStreamingSIMDExtensions );
- RexRB(0, from, to);
- write16(0x170f);
- WriteRmOffsetFrom(from, to, 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, uptr 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, uptr 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, uptr 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, uptr from ) { SSE_SS_MtoR(0x530f, 0); }
-
-//////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//ORPS : Bit-wise Logical OR of Single-Precision FP Data *
-//**********************************************************************************
-void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from ) { CMPPSMtoR( 0 ); }
-void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); }
-void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 1 ); }
-void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); }
-void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 2 ); }
-void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); }
-void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 3 ); }
-void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); }
-void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 4 ); }
-void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); }
-void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 5 ); }
-void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); }
-void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 6 ); }
-void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); }
-void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from ) { CMPSSMtoR( 0 ); }
-void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); }
-void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 1 ); }
-void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); }
-void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 2 ); }
-void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); }
-void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 3 ); }
-void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); }
-void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 4 ); }
-void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); }
-void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 5 ); }
-void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); }
-void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 6 ); }
-void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); }
-void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 7 ); }
-void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); }
-
-void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from )
-{
- MEMADDR_OP(0, VAROP2(0x0F, 0x2E), true, to, from, 0);
-}
-
-void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from )
-{
- RexRB(0, to, from);
- write16( 0x2e0f );
- ModRM( 3, to, from );
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal *
-//**********************************************************************************
-void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from ) { SSE_SS_MtoR( 0x5f0f, 0 ); }
-void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); }
-
-#ifndef __x86_64__
-/////////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion *
-//**********************************************************************************
-void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr 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, uptr from ) { SSEMtoR( 0x2d0f, 0 ); }
-void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); }
-#endif
-
-void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from) { SSE_SS_MtoR(0x2c0f, 0); }
-void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from)
-{
- write8(0xf3);
- RexRB(0, to, from);
- write16(0x2c0f);
- ModRM(3, to, from);
-}
-
-void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from) { SSE_SS_MtoR(0x2a0f, 0); }
-void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from)
-{
- write8(0xf3);
- RexRB(0, to, from);
- write16(0x2a0f);
- ModRM(3, to, from);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion *
-//**********************************************************************************
-void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from ) { SSEMtoR66( 0x5b0f ); }
-void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); }
-
-void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x5b0f); }
-/////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//MINPS: Return Packed Single-Precision FP Minimum *
-//**********************************************************************************
-void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from ) { SSE_SS_MtoR( 0x5d0f, 0 ); }
-void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); }
-
-#ifndef __x86_64__
-///////////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//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 ); }
-#endif
-
-//////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//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, uptr from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); }
-
-void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 )
-{
- RexRB(0, to, from);
- write16(0xc60f);
- WriteRmOffsetFrom(to, from, 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, uptr from, u8 imm8 ) { SSEMtoRv( 3, 0x700F66, 1 ); 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, uptr from, u8 imm8 ) { SSEMtoRv(3, 0x700FF2, 1); write8(imm8); }
-void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSE_SS_RtoR(0x700F); write8(imm8); }
-void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSE_SS_MtoR(0x700F, 1); write8(imm8); }
-
-///////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data *
-//**********************************************************************************
-void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr 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( uptr from ) {
- MEMADDR_OP(0, VAROP2(0x0F, 0xAE), false, 3, from, 0);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//LDMXCSR : Load Streaming SIMD Extension Control/Status *
-//**********************************************************************************
-void SSE_LDMXCSR( uptr from ) {
- MEMADDR_OP(0, VAROP2(0x0F, 0xAE), false, 2, from, 0);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//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, uptr from ){ SSEMtoR66( 0xFC0F ); }
-void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); }
-void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFD0F ); }
-void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); }
-void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFE0F ); }
-
-void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); }
-void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from ){ SSEMtoR66( 0x640F ); }
-void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); }
-void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x650F ); }
-void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); }
-void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x660F ); }
-void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); }
-void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x740F ); }
-void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); }
-void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr 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, uptr 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, uptr from ){ SSEMtoR66( 0xF80F ); }
-void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); }
-void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF90F ); }
-void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); }
-void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFA0F ); }
-void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); }
-void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFB0F ); }
-
-///////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//MOVD: Move Dword(32bit) to /from XMM reg *
-//**********************************************************************************
-void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr 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);
- RexRB(0, to, from);
- write16( 0x6e0f );
- ModRM( 0, to, from);
-}
-
-void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
-{
- write8(0x66);
- RexRB(0, to, from);
- write16( 0x6e0f );
- WriteRmOffsetFrom(to, from, 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);
- RexRB(0, from, to);
- write16( 0x7e0f );
- ModRM( 0, from, to );
-}
-
-void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
-{
- if( !cpucaps.hasStreamingSIMD2Extensions ) {
- SSE2EMU_MOVD_XMM_to_RmOffset(to, from, offset);
- }
- else {
- write8(0x66);
- RexRB(0, from, to);
- write16( 0x7e0f );
- WriteRmOffsetFrom(from, to, offset);
- }
-}
-
-#ifdef __x86_64__
-void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from )
-{
- assert( from < XMMREGS);
- write8( 0x66 );
- RexRB(1, from, to);
- write16( 0x7e0f );
- ModRM( 3, from, to );
-}
-
-void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from )
-{
- assert( to < XMMREGS);
- write8(0x66);
- RexRB(1, to, from);
- write16( 0x6e0f );
- ModRM( 3, to, from );
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////////
-//**********************************************************************************/
-//POR : SSE Bitwise OR *
-//**********************************************************************************
-void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); }
-void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr from ){ SSEMtoR66( 0xEF0F ); }
-///////////////////////////////////////////////////////////////////////////////////////
-
-void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from) {SSEMtoR66(0x6F0F); }
-void SSE2_MOVDQA_XMM_to_M128( uptr 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, uptr from) { SSE_SS_MtoR(0x6F0F, 0); }
-void SSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from) { SSE_SS_RtoM(0x7F0F, 0); }
-void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSE_SS_RtoR(0x6F0F); }
-
-// shift right logical
-
-void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); }
-void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD10F); }
-void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xD20F); }
-void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xD30F); }
-void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- write16( 0x730F );
- ModRM( 3, 2 , to );
- write8( imm8 );
-}
-
-void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xE10F); }
-void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xE20F); }
-void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xF10F); }
-void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xF20F); }
-void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from) { SSEMtoR66(0xF30F); }
-void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- write16( 0x730F );
- ModRM( 3, 6 , to );
- write8( imm8 );
-}
-
-void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8)
-{
- write8( 0x66 );
- RexB(0, to);
- 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, uptr from ){ SSEMtoR66( 0xEE0F ); }
-
-void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDE0F ); }
-void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xDE0F ); }
-
-void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEA0F ); }
-void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEA0F ); }
-
-void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDA0F ); }
-void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xDA0F ); }
-
-//
-
-void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEC0F ); }
-void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEC0F ); }
-
-void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xED0F ); }
-void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xED0F ); }
-
-void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE80F ); }
-void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xE80F ); }
-
-void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE90F ); }
-void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xE90F ); }
-
-void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); }
-void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD80F ); }
-void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); }
-void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD90F ); }
-
-void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); }
-void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDC0F ); }
-void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); }
-void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr 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, uptr from) { SSEMtoR66( 0x630F ); }
-void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); }
-void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6B0F ); }
-
-void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); }
-void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr 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, uptr from) { SSEMtoR66( 0x600F ); }
-
-void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); }
-void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x680F ); }
-
-void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); }
-void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x610F ); }
-void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); }
-void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x690F ); }
-
-void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); }
-void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x620F ); }
-void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); }
-void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6A0F ); }
-
-void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); }
-void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6C0F ); }
-
-void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); }
-void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6D0F ); }
-
-void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); }
-void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xD50F ); }
-void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); }
-void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xE50F ); }
-
-void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); }
-void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from){ SSEMtoRv( 3, 0x7c0fF2, 0 ); }
-
-void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) {
- write8(0xf3);
- RexRB(0, to, from);
- write16( 0x120f);
- ModRM( 3, to, from );
-}
-
-void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from) { SSE_SS_MtoR(0x120f, 0); }
-void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSE_SS_RtoR(0x160f); }
-void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr from) { SSE_SS_MtoR(0x160f, 0); }
-
-// SSE-X
-void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr 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( uptr 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, int 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, int 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, uptr 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( uptr 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, uptr 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, int 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, int 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, int offset )
-{
- MOV32RmtoROffset(EAX, from, offset);
- MOV32ItoM((uptr)p+4, 0);
- MOV32ItoM((uptr)p+8, 0);
- MOV32RtoM((uptr)p, EAX);
- MOV32ItoM((uptr)p+12, 0);
- SSE_MOVAPS_M128_to_XMM(to, (uptr)p);
-}
-
-void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, int offset )
-{
- SSE_MOVSS_XMM_to_M32((uptr)p, from);
- MOV32MtoR(EAX, (uptr)p);
- MOV32RtoRmOffset(to, EAX, offset);
-}
-
-#ifndef __x86_64__
-extern void SetMMXstate();
-
-void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from)
-{
- SSE_MOVLPS_XMM_to_M64(p, from);
- MOVQMtoR(to, p);
- SetMMXstate();
-}
-
-void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from)
-{
- MOVQRtoM(p, from);
- SSE_MOVLPS_M64_to_XMM(to, p);
- SetMMXstate();
-}
-#endif
-
-/****************************************************************************/
-/* SSE2 Emulated functions for SSE CPU's by kekko */
-/****************************************************************************/
-void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) {
- MOV64ItoR(EAX, (uptr)&p);
- MOV64ItoR(EBX, (uptr)&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 ) {
- /* XXX? */
- MOV64ItoR(to, (uptr)&p);
- SSE_MOVUPSRtoRm(to, from);
- MOV32RmtoR(to, to);
-}
-
-#ifndef __x86_64__
-extern void SetFPUstate();
-extern void _freeMMXreg(int mmxreg);
-#endif
-
-void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) {
-#ifndef __x86_64__
- SetFPUstate();
- _freeMMXreg(7);
-#endif
- SSE_MOVAPS_XMM_to_M128((uptr)f, from);
-
- FLD32((uptr)&f[0]);
- FISTP32((uptr)&p2[0]);
- FLD32((uptr)&f[1]);
- FISTP32((uptr)&p2[1]);
- FLD32((uptr)&f[2]);
- FISTP32((uptr)&p2[2]);
- FLD32((uptr)&f[3]);
- FISTP32((uptr)&p2[3]);
-
- SSE_MOVAPS_M128_to_XMM(to, (uptr)p2);
-}
-
-void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) {
-#ifndef __x86_64__
- SetFPUstate();
- _freeMMXreg(7);
-#endif
- FILD32(from);
- FSTP32((uptr)&f[0]);
- FILD32(from+4);
- FSTP32((uptr)&f[1]);
- FILD32(from+8);
- FSTP32((uptr)&f[2]);
- FILD32(from+12);
- FSTP32((uptr)&f[3]);
-
- SSE_MOVAPS_M128_to_XMM(to, (uptr)f);
-}
-
-void SSE2EMU_MOVD_XMM_to_M32( uptr to, x86SSERegType from ) {
- /* XXX? */
- MOV64ItoR(EAX, (uptr)&p);
- SSE_MOVUPSRtoRm(EAX, from);
- MOV32RmtoR(EAX, EAX);
- MOV32RtoM(to, EAX);
-}
-
-void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) {
- MOV32ItoM((uptr)p+4, 0);
- MOV32ItoM((uptr)p+8, 0);
- MOV32RtoM((uptr)p, from);
- MOV32ItoM((uptr)p+12, 0);
- SSE_MOVAPS_M128_to_XMM(to, (uptr)p);
-}
-
-#endif
-
-#endif
+// stop compiling if NORECBUILD build (only for Visual Studio) + +#ifdef __x86_64__ + +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include <assert.h> +#include "ix86-64.h" + +PCSX2_ALIGNED16(static unsigned int p[4]); +PCSX2_ALIGNED16(static unsigned int p2[4]); +PCSX2_ALIGNED16(static float f[4]); + + +XMMSSEType g_xmmtypes[XMMREGS] = {0}; + +/********************/ +/* SSE instructions */ +/********************/ + +#define SSEMtoRv( nc, code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS ) ; \ + MEMADDR_OP(0, nc, code, true, to, from, overb) + +#define SSEMtoR( code, overb ) SSEMtoRv(2, code, overb) + +#define SSERtoMv( nc, code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( from < XMMREGS) ; \ + MEMADDR_OP(0, nc, code, true, from, to, overb) + +#define SSERtoM( code, overb ) SSERtoMv( 2, code, overb ) \ + +#define SSE_SS_MtoR( code, overb ) \ + SSEMtoRv(3, (code << 8) | 0xF3, overb) + +#define SSE_SS_RtoM( code, overb ) \ + SSERtoMv(3, (code << 8) | 0xF3, overb) + +#define SSERtoR( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + RexRB(0, to, from); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define SSEMtoR66( code ) \ + SSEMtoRv( 3, (code << 8) | 0x66, 0 ) + +#define SSERtoM66( code ) \ + SSERtoMv( 3, (code << 8) | 0x66, 0 ) + +#define SSERtoR66( code ) \ + write8( 0x66 ); \ + SSERtoR( code ); + +#define _SSERtoR66( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + write8( 0x66 ); \ + RexRB(0, from, to); \ + write16( code ); \ + ModRM( 3, from, to ); + +#define SSE_SS_RtoR( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + write8( 0xf3 ); \ + RexRB(0, to, from); \ + 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 ); + + + +void WriteRmOffset(x86IntRegType to, int offset); +void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset); + +/* movups [r32][r32*scale] to xmm1 */ +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRXB(0, to, from2, from); + 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 ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRXB(1, to, from2, from); + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups [r32] to r32 */ +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x100f ); + ModRM( 0, to, from ); +} + +/* movups r32 to [r32] */ +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x110f ); + ModRM( 0, from, to ); +} + +/* movlps [r32] to r32 */ +void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(1, to, from); + write16( 0x120f ); + ModRM( 0, to, from ); +} + +void SSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x120f ); + WriteRmOffsetFrom(to, from, offset); +} + +/* movaps r32 to [r32] */ +void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x130f ); + ModRM( 0, from, to ); +} + +void SSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x130f ); + WriteRmOffsetFrom(from, to, offset); +} + +/* movaps [r32][r32*scale] to xmm1 */ +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions && from != EBP ); + RexRXB(0, to, from2, from); + write16( 0x280f ); + 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 ) +{ + assert( cpucaps.hasStreamingSIMDExtensions && from != EBP ); + RexRXB(0, to, from2, from); + write16( 0x290f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +// movaps [r32+offset] to r32 +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x280f ); + WriteRmOffsetFrom(to, from, offset); +} + +// movaps r32 to [r32+offset] +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x290f ); + WriteRmOffsetFrom(from, to, offset); +} + +// movdqa [r32+offset] to r32 +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write8(0x66); + RexRB(0, to, from); + write16( 0x6f0f ); + WriteRmOffsetFrom(to, from, offset); +} + +// movdqa r32 to [r32+offset] +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write8(0x66); + RexRB(0, from, to); + write16( 0x7f0f ); + WriteRmOffsetFrom(from, to, offset); +} + +// movups [r32+offset] to r32 +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + RexRB(0, to, from); + write16( 0x100f ); + WriteRmOffsetFrom(to, from, offset); +} + +// movups r32 to [r32+offset] +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x110f ); + WriteRmOffsetFrom(from, to, offset); +} + +//**********************************************************************************/ +//MOVAPS: Move aligned Packed Single Precision FP values * +//********************************************************************************** +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); } +void SSE_MOVAPS_XMM_to_M128( uptr 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, uptr from ) { SSEMtoR( 0x100f, 0 ); } +void SSE_MOVUPS_XMM_to_M128( uptr 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, uptr from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_M64_to_XMM(to, from); + else { + SSE_SS_MtoR( 0x7e0f, 0); + } +} + +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_XMM_to_XMM(to, from); + else { + SSE_SS_RtoR( 0x7e0f); + } +} + +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVLPS_XMM_to_M64(to, from); + else { + SSERtoM66(0xd60f); + } +} + +#ifndef __x86_64__ +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 { + SSE_SS_RtoR( 0xd60f); + } +} +#endif + +//**********************************************************************************/ +//MOVSS: Move Scalar Single-Precision FP value * +//********************************************************************************** +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr 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); + RexRB(0, from, to); + 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, int offset ) +{ + write8(0xf3); + RexRB(0, to, from); + write16( 0x100f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + write8(0xf3); + RexRB(0, from, to); + write16(0x110f); + WriteRmOffsetFrom(from, to, 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, uptr 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, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x120f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + RexRB(0, from, to); + write16(0x130f); + WriteRmOffsetFrom(from, to, offset); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHPS: Move High Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr 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, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x160f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16(0x170f); + WriteRmOffsetFrom(from, to, 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, uptr 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, uptr 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, uptr 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, uptr from ) { SSE_SS_MtoR(0x530f, 0); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ORPS : Bit-wise Logical OR of Single-Precision FP Data * +//********************************************************************************** +void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from ) { CMPPSMtoR( 0 ); } +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); } +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 1 ); } +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); } +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 2 ); } +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); } +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 3 ); } +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); } +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 4 ); } +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); } +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 5 ); } +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); } +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 6 ); } +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); } +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from ) { CMPSSMtoR( 0 ); } +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); } +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 1 ); } +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); } +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 2 ); } +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); } +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 3 ); } +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); } +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 4 ); } +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); } +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 5 ); } +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); } +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 6 ); } +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); } +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 7 ); } +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); } + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x2E), true, to, from, 0); +} + +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + RexRB(0, to, from); + write16( 0x2e0f ); + ModRM( 3, to, from ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr from ) { SSE_SS_MtoR( 0x5f0f, 0 ); } +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); } + +#ifndef __x86_64__ +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion * +//********************************************************************************** +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr 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, uptr from ) { SSEMtoR( 0x2d0f, 0 ); } +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); } +#endif + +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from) { SSE_SS_MtoR(0x2c0f, 0); } +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) +{ + write8(0xf3); + RexRB(0, to, from); + write16(0x2c0f); + ModRM(3, to, from); +} + +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from) { SSE_SS_MtoR(0x2a0f, 0); } +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) +{ + write8(0xf3); + RexRB(0, to, from); + write16(0x2a0f); + ModRM(3, to, from); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion * +//********************************************************************************** +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from ) { SSEMtoR66( 0x5b0f ); } +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); } + +void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x5b0f); } +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINPS: Return Packed Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr from ) { SSE_SS_MtoR( 0x5d0f, 0 ); } +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); } + +#ifndef __x86_64__ +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//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 ); } +#endif + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//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, uptr from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); } + +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ) +{ + RexRB(0, to, from); + write16(0xc60f); + WriteRmOffsetFrom(to, from, 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, uptr from, u8 imm8 ) { SSEMtoRv( 3, 0x700F66, 1 ); 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, uptr from, u8 imm8 ) { SSEMtoRv(3, 0x700FF2, 1); write8(imm8); } +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSE_SS_RtoR(0x700F); write8(imm8); } +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSE_SS_MtoR(0x700F, 1); write8(imm8); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr 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( uptr from ) { + MEMADDR_OP(0, VAROP2(0x0F, 0xAE), false, 3, from, 0); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//LDMXCSR : Load Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_LDMXCSR( uptr from ) { + MEMADDR_OP(0, VAROP2(0x0F, 0xAE), false, 2, from, 0); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//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, uptr from ){ SSEMtoR66( 0xFC0F ); } +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); } +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFD0F ); } +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); } +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFE0F ); } + +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); } +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from ){ SSEMtoR66( 0x640F ); } +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); } +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x650F ); } +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); } +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x660F ); } +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); } +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x740F ); } +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); } +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr 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, uptr 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, uptr from ){ SSEMtoR66( 0xF80F ); } +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); } +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF90F ); } +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); } +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFA0F ); } +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); } +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFB0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr 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); + RexRB(0, to, from); + write16( 0x6e0f ); + ModRM( 0, to, from); +} + +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + write8(0x66); + RexRB(0, to, from); + write16( 0x6e0f ); + WriteRmOffsetFrom(to, from, 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); + RexRB(0, from, to); + write16( 0x7e0f ); + ModRM( 0, from, to ); +} + +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_RmOffset(to, from, offset); + } + else { + write8(0x66); + RexRB(0, from, to); + write16( 0x7e0f ); + WriteRmOffsetFrom(from, to, offset); + } +} + +#ifdef __x86_64__ +void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from ) +{ + assert( from < XMMREGS); + write8( 0x66 ); + RexRB(1, from, to); + write16( 0x7e0f ); + ModRM( 3, from, to ); +} + +void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + assert( to < XMMREGS); + write8(0x66); + RexRB(1, to, from); + write16( 0x6e0f ); + ModRM( 3, to, from ); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); } +void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr 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, uptr 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, uptr 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, uptr from ){ SSEMtoR66( 0xEF0F ); } +/////////////////////////////////////////////////////////////////////////////////////// + +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from) {SSEMtoR66(0x6F0F); } +void SSE2_MOVDQA_XMM_to_M128( uptr 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, uptr from) { SSE_SS_MtoR(0x6F0F, 0); } +void SSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from) { SSE_SS_RtoM(0x7F0F, 0); } +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSE_SS_RtoR(0x6F0F); } + +// shift right logical + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); } +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD10F); } +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xD20F); } +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xD30F); } +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xE10F); } +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xE20F); } +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xF10F); } +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xF20F); } +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from) { SSEMtoR66(0xF30F); } +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + 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, uptr from ){ SSEMtoR66( 0xEE0F ); } + +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDE0F ); } +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xDE0F ); } + +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEA0F ); } +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEA0F ); } + +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDA0F ); } +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xDA0F ); } + +// + +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEC0F ); } +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEC0F ); } + +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xED0F ); } +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xED0F ); } + +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE80F ); } +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xE80F ); } + +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE90F ); } +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xE90F ); } + +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); } +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD80F ); } +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); } +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD90F ); } + +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); } +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDC0F ); } +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); } +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr 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, uptr from) { SSEMtoR66( 0x630F ); } +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); } +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6B0F ); } + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); } +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr 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, uptr from) { SSEMtoR66( 0x600F ); } + +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); } +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x680F ); } + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); } +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x610F ); } +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); } +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x690F ); } + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); } +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x620F ); } +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); } +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6A0F ); } + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); } +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6C0F ); } + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); } +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6D0F ); } + +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); } +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xD50F ); } +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); } +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xE50F ); } + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); } +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr 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, uptr from){ SSEMtoRv( 3, 0x7c0fF2, 0 ); } + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { + write8(0xf3); + RexRB(0, to, from); + write16( 0x120f); + ModRM( 3, to, from ); +} + +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from) { SSE_SS_MtoR(0x120f, 0); } +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSE_SS_RtoR(0x160f); } +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr from) { SSE_SS_MtoR(0x160f, 0); } + +// SSE-X +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr 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( uptr 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, int 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, int 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, uptr 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( uptr 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, uptr 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, int 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, int 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, uptr 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, int offset ) +{ + MOV32RmtoROffset(EAX, from, offset); + MOV32ItoM((uptr)p+4, 0); + MOV32ItoM((uptr)p+8, 0); + MOV32RtoM((uptr)p, EAX); + MOV32ItoM((uptr)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (uptr)p); +} + +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, int offset ) +{ + SSE_MOVSS_XMM_to_M32((uptr)p, from); + MOV32MtoR(EAX, (uptr)p); + MOV32RtoRmOffset(to, EAX, offset); +} + +#ifndef __x86_64__ +extern void SetMMXstate(); + +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + SSE_MOVLPS_XMM_to_M64(p, from); + MOVQMtoR(to, p); + SetMMXstate(); +} + +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + MOVQRtoM(p, from); + SSE_MOVLPS_M64_to_XMM(to, p); + SetMMXstate(); +} +#endif + +/****************************************************************************/ +/* SSE2 Emulated functions for SSE CPU's by kekko */ +/****************************************************************************/ +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { + MOV64ItoR(EAX, (uptr)&p); + MOV64ItoR(EBX, (uptr)&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 ) { + /* XXX? */ + MOV64ItoR(to, (uptr)&p); + SSE_MOVUPSRtoRm(to, from); + MOV32RmtoR(to, to); +} + +#ifndef __x86_64__ +extern void SetFPUstate(); +extern void _freeMMXreg(int mmxreg); +#endif + +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { +#ifndef __x86_64__ + SetFPUstate(); + _freeMMXreg(7); +#endif + SSE_MOVAPS_XMM_to_M128((uptr)f, from); + + FLD32((uptr)&f[0]); + FISTP32((uptr)&p2[0]); + FLD32((uptr)&f[1]); + FISTP32((uptr)&p2[1]); + FLD32((uptr)&f[2]); + FISTP32((uptr)&p2[2]); + FLD32((uptr)&f[3]); + FISTP32((uptr)&p2[3]); + + SSE_MOVAPS_M128_to_XMM(to, (uptr)p2); +} + +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) { +#ifndef __x86_64__ + SetFPUstate(); + _freeMMXreg(7); +#endif + FILD32(from); + FSTP32((uptr)&f[0]); + FILD32(from+4); + FSTP32((uptr)&f[1]); + FILD32(from+8); + FSTP32((uptr)&f[2]); + FILD32(from+12); + FSTP32((uptr)&f[3]); + + SSE_MOVAPS_M128_to_XMM(to, (uptr)f); +} + +void SSE2EMU_MOVD_XMM_to_M32( uptr to, x86SSERegType from ) { + /* XXX? */ + MOV64ItoR(EAX, (uptr)&p); + SSE_MOVUPSRtoRm(EAX, from); + MOV32RmtoR(EAX, EAX); + MOV32RtoM(to, EAX); +} + +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { + MOV32ItoM((uptr)p+4, 0); + MOV32ItoM((uptr)p+8, 0); + MOV32RtoM((uptr)p, from); + MOV32ItoM((uptr)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (uptr)p); +} + +#endif + +#endif diff --git a/libpcsxcore/mdec.c b/libpcsxcore/mdec.c index 58d3c1e4..4da1e637 100644..100755 --- a/libpcsxcore/mdec.c +++ b/libpcsxcore/mdec.c @@ -1,678 +1,678 @@ -/***************************************************************************
- * Copyright (C) 2010 Gabriele Gorla *
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#include "mdec.h"
-
-/* memory speed is 1 byte per MDEC_BIAS psx clock
- * That mean (PSXCLK / MDEC_BIAS) B/s
- * MDEC_BIAS = 2.0 => ~16MB/s
- * MDEC_BIAS = 3.0 => ~11MB/s
- * and so on ...
- * I guess I have 50 images in 50Hz ... (could be 25 images ?)
- * 320x240x24@50Hz => 11.52 MB/s
- * 320x240x24@60Hz => 13.824 MB/s
- * 320x240x16@50Hz => 7.68 MB/s
- * 320x240x16@60Hz => 9.216 MB/s
- * so 2.0 to 4.0 should be fine.
- */
-#define MDEC_BIAS 2.0f
-
-#define DSIZE 8
-#define DSIZE2 (DSIZE * DSIZE)
-
-#define SCALE(x, n) ((x) >> (n))
-#define SCALER(x, n) (((x) + ((1 << (n)) >> 1)) >> (n))
-
-#define AAN_CONST_BITS 12
-#define AAN_PRESCALE_BITS 16
-
-#define AAN_CONST_SIZE 24
-#define AAN_CONST_SCALE (AAN_CONST_SIZE - AAN_CONST_BITS)
-
-#define AAN_PRESCALE_SIZE 20
-#define AAN_PRESCALE_SCALE (AAN_PRESCALE_SIZE-AAN_PRESCALE_BITS)
-#define AAN_EXTRA 12
-
-#define FIX_1_082392200 SCALER(18159528, AAN_CONST_SCALE) // B6
-#define FIX_1_414213562 SCALER(23726566, AAN_CONST_SCALE) // A4
-#define FIX_1_847759065 SCALER(31000253, AAN_CONST_SCALE) // A2
-#define FIX_2_613125930 SCALER(43840978, AAN_CONST_SCALE) // B2
-
-#define MULS(var, const) (SCALE((var) * (const), AAN_CONST_BITS))
-
-#define RLE_RUN(a) ((a) >> 10)
-#define RLE_VAL(a) (((int)(a) << (sizeof(int) * 8 - 10)) >> (sizeof(int) * 8 - 10))
-
-#if 0
-static void printmatrixu8(u8 *m) {
- int i;
- for(i = 0; i < DSIZE2; i++) {
- printf("%3d ",m[i]);
- if((i+1) % 8 == 0) printf("\n");
- }
-}
-#endif
-
-static inline void fillcol(int *blk, int val) {
- blk[0 * DSIZE] = blk[1 * DSIZE] = blk[2 * DSIZE] = blk[3 * DSIZE]
- = blk[4 * DSIZE] = blk[5 * DSIZE] = blk[6 * DSIZE] = blk[7 * DSIZE] = val;
-}
-
-static inline void fillrow(int *blk, int val) {
- blk[0] = blk[1] = blk[2] = blk[3]
- = blk[4] = blk[5] = blk[6] = blk[7] = val;
-}
-
-void idct(int *block,int used_col) {
- int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
- int z5, z10, z11, z12, z13;
- int *ptr;
- int i;
-
- // the block has only the DC coefficient
- if (used_col == -1) {
- int v = block[0];
- for (i = 0; i < DSIZE2; i++) block[i] = v;
- return;
- }
-
- // last_col keeps track of the highest column with non zero coefficients
- ptr = block;
- for (i = 0; i < DSIZE; i++, ptr++) {
- if ((used_col & (1 << i)) == 0) {
- // the column is empty or has only the DC coefficient
- if (ptr[DSIZE * 0]) {
- fillcol(ptr, ptr[0]);
- used_col |= (1 << i);
- }
- continue;
- }
-
- // further optimization could be made by keeping track of
- // last_row in rl2blk
- z10 = ptr[DSIZE * 0] + ptr[DSIZE * 4]; // s04
- z11 = ptr[DSIZE * 0] - ptr[DSIZE * 4]; // d04
- z13 = ptr[DSIZE * 2] + ptr[DSIZE * 6]; // s26
- z12 = MULS(ptr[DSIZE * 2] - ptr[DSIZE * 6], FIX_1_414213562) - z13;
- //^^^^ d26=d26*2*A4-s26
-
- tmp0 = z10 + z13; // os07 = s04 + s26
- tmp3 = z10 - z13; // os34 = s04 - s26
- tmp1 = z11 + z12; // os16 = d04 + d26
- tmp2 = z11 - z12; // os25 = d04 - d26
-
- z13 = ptr[DSIZE * 3] + ptr[DSIZE * 5]; //s53
- z10 = ptr[DSIZE * 3] - ptr[DSIZE * 5]; //-d53
- z11 = ptr[DSIZE * 1] + ptr[DSIZE * 7]; //s17
- z12 = ptr[DSIZE * 1] - ptr[DSIZE * 7]; //d17
-
- tmp7 = z11 + z13; // od07 = s17 + s53
-
- z5 = (z12 - z10) * (FIX_1_847759065);
- tmp6 = SCALE(z10*(FIX_2_613125930) + z5, AAN_CONST_BITS) - tmp7;
- tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6;
- tmp4 = SCALE(z12*(FIX_1_082392200) - z5, AAN_CONST_BITS) + tmp5;
-
- // path #1
- //z5 = (z12 - z10)* FIX_1_847759065;
- // tmp0 = (d17 + d53) * 2*A2
-
- //tmp6 = DESCALE(z10*FIX_2_613125930 + z5, CONST_BITS) - tmp7;
- // od16 = (d53*-2*B2 + tmp0) - od07
-
- //tmp4 = DESCALE(z12*FIX_1_082392200 - z5, CONST_BITS) + tmp5;
- // od34 = (d17*2*B6 - tmp0) + od25
-
- // path #2
-
- // od34 = d17*2*(B6-A2) - d53*2*A2
- // od16 = d53*2*(A2-B2) + d17*2*A2
-
- // end
-
- // tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6;
- // od25 = (s17 - s53)*2*A4 - od16
-
- ptr[DSIZE * 0] = (tmp0 + tmp7); // os07 + od07
- ptr[DSIZE * 7] = (tmp0 - tmp7); // os07 - od07
- ptr[DSIZE * 1] = (tmp1 + tmp6); // os16 + od16
- ptr[DSIZE * 6] = (tmp1 - tmp6); // os16 - od16
- ptr[DSIZE * 2] = (tmp2 + tmp5); // os25 + od25
- ptr[DSIZE * 5] = (tmp2 - tmp5); // os25 - od25
- ptr[DSIZE * 4] = (tmp3 + tmp4); // os34 + od34
- ptr[DSIZE * 3] = (tmp3 - tmp4); // os34 - od34
- }
-
- ptr = block;
- if (used_col == 1) {
- for (i = 0; i < DSIZE; i++)
- fillrow(block + DSIZE * i, block[DSIZE * i]);
- } else {
- for (i = 0; i < DSIZE; i++, ptr += DSIZE) {
- z10 = ptr[0] + ptr[4];
- z11 = ptr[0] - ptr[4];
- z13 = ptr[2] + ptr[6];
- z12 = MULS(ptr[2] - ptr[6], FIX_1_414213562) - z13;
-
- tmp0 = z10 + z13;
- tmp3 = z10 - z13;
- tmp1 = z11 + z12;
- tmp2 = z11 - z12;
-
- z13 = ptr[3] + ptr[5];
- z10 = ptr[3] - ptr[5];
- z11 = ptr[1] + ptr[7];
- z12 = ptr[1] - ptr[7];
-
- tmp7 = z11 + z13;
- z5 = (z12 - z10) * FIX_1_847759065;
- tmp6 = SCALE(z10 * FIX_2_613125930 + z5, AAN_CONST_BITS) - tmp7;
- tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6;
- tmp4 = SCALE(z12 * FIX_1_082392200 - z5, AAN_CONST_BITS) + tmp5;
-
- ptr[0] = tmp0 + tmp7;
-
- ptr[7] = tmp0 - tmp7;
- ptr[1] = tmp1 + tmp6;
- ptr[6] = tmp1 - tmp6;
- ptr[2] = tmp2 + tmp5;
- ptr[5] = tmp2 - tmp5;
- ptr[4] = tmp3 + tmp4;
- ptr[3] = tmp3 - tmp4;
- }
- }
-}
-
-// mdec0: command register
-#define MDEC0_STP 0x02000000
-#define MDEC0_RGB24 0x08000000
-#define MDEC0_SIZE_MASK 0x0000FFFF
-
-// mdec1: status register
-#define MDEC1_BUSY 0x20000000
-#define MDEC1_DREQ 0x18000000
-#define MDEC1_FIFO 0xc0000000
-#define MDEC1_RGB24 0x02000000
-#define MDEC1_STP 0x00800000
-#define MDEC1_RESET 0x80000000
-
-struct _pending_dma1 {
- u32 adr;
- u32 bcr;
- u32 chcr;
-};
-
-static struct {
- u32 reg0;
- u32 reg1;
- u16 * rl;
- u16 * rl_end;
- u8 * block_buffer_pos;
- u8 block_buffer[16*16*3];
- struct _pending_dma1 pending_dma1;
-} mdec;
-
-static int iq_y[DSIZE2], iq_uv[DSIZE2];
-
-static int zscan[DSIZE2] = {
- 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[DSIZE2] = {
- 1048576, 1454417, 1370031, 1232995, 1048576, 823861, 567485, 289301,
- 1454417, 2017334, 1900287, 1710213, 1454417, 1142728, 787125, 401273,
- 1370031, 1900287, 1790031, 1610986, 1370031, 1076426, 741455, 377991,
- 1232995, 1710213, 1610986, 1449849, 1232995, 968758, 667292, 340183,
- 1048576, 1454417, 1370031, 1232995, 1048576, 823861, 567485, 289301,
- 823861, 1142728, 1076426, 968758, 823861, 647303, 445870, 227303,
- 567485, 787125, 741455, 667292, 567485, 445870, 307121, 156569,
- 289301, 401273, 377991, 340183, 289301, 227303, 156569, 79818
-};
-
-static void iqtab_init(int *iqtab, unsigned char *iq_y) {
- int i;
-
- for (i = 0; i < DSIZE2; i++) {
- iqtab[i] = (iq_y[i] * SCALER(aanscales[zscan[i]], AAN_PRESCALE_SCALE));
- }
-}
-
-#define MDEC_END_OF_DATA 0xfe00
-
-unsigned short *rl2blk(int *blk, unsigned short *mdec_rl) {
- int i, k, q_scale, rl, used_col;
- int *iqtab;
-
- memset(blk, 0, 6 * DSIZE2 * sizeof(int));
- iqtab = iq_uv;
- for (i = 0; i < 6; i++) {
- // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4)
- if (i == 2) iqtab = iq_y;
-
- rl = SWAP16(*mdec_rl); mdec_rl++;
- q_scale = RLE_RUN(rl);
- blk[0] = SCALER(iqtab[0] * RLE_VAL(rl), AAN_EXTRA - 3);
- for (k = 0, used_col = 0;;) {
- rl = SWAP16(*mdec_rl); mdec_rl++;
- if (rl == MDEC_END_OF_DATA) break;
- k += RLE_RUN(rl) + 1; // skip zero-coefficients
-
- if (k > 63) {
- // printf("run lenght exceeded 64 enties\n");
- break;
- }
-
- // zigzag transformation
- blk[zscan[k]] = SCALER(RLE_VAL(rl) * iqtab[k] * q_scale, AAN_EXTRA);
- // keep track of used columns to speed up the idtc
- used_col |= (zscan[k] > 7) ? 1 << (zscan[k] & 7) : 0;
- }
-
- if (k == 0) used_col = -1;
- // used_col is -1 for blocks with only the DC coefficient
- // any other value is a bitmask of the columns that have
- // at least one non zero cofficient in the rows 1-7
- // single coefficients in row 0 are treted specially
- // in the idtc function
- idct(blk, used_col);
- blk += DSIZE2;
- }
- return mdec_rl;
-}
-
-// full scale (JPEG)
-// Y/Cb/Cr[0...255] -> R/G/B[0...255]
-// R = 1.000 * (Y) + 1.400 * (Cr - 128)
-// G = 1.000 * (Y) - 0.343 * (Cb - 128) - 0.711 (Cr - 128)
-// B = 1.000 * (Y) + 1.765 * (Cb - 128)
-#define MULR(a) ((1434 * (a)))
-#define MULB(a) ((1807 * (a)))
-#define MULG2(a, b) ((-351 * (a) - 728 * (b)))
-#define MULY(a) ((a) << 10)
-
-#define MAKERGB15(r, g, b, a) (SWAP16(a | ((b) << 10) | ((g) << 5) | (r)))
-#define SCALE8(c) SCALER(c, 20)
-#define SCALE5(c) SCALER(c, 23)
-
-#define CLAMP5(c) ( ((c) < -16) ? 0 : (((c) > (31 - 16)) ? 31 : ((c) + 16)) )
-#define CLAMP8(c) ( ((c) < -128) ? 0 : (((c) > (255 - 128)) ? 255 : ((c) + 128)) )
-
-#define CLAMP_SCALE8(a) (CLAMP8(SCALE8(a)))
-#define CLAMP_SCALE5(a) (CLAMP5(SCALE5(a)))
-
-static inline void putlinebw15(u16 *image, int *Yblk) {
- int i;
- int A = (mdec.reg0 & MDEC0_STP) ? 0x8000 : 0;
-
- for (i = 0; i < 8; i++, Yblk++) {
- int Y = *Yblk;
- // missing rounding
- image[i] = SWAP16((CLAMP5(Y >> 3) * 0x421) | A);
- }
-}
-
-static inline void putquadrgb15(u16 *image, int *Yblk, int Cr, int Cb) {
- int Y, R, G, B;
- int A = (mdec.reg0 & MDEC0_STP) ? 0x8000 : 0;
- R = MULR(Cr);
- G = MULG2(Cb, Cr);
- B = MULB(Cb);
-
- // added transparency
- Y = MULY(Yblk[0]);
- image[0] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
- Y = MULY(Yblk[1]);
- image[1] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
- Y = MULY(Yblk[8]);
- image[16] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
- Y = MULY(Yblk[9]);
- image[17] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
-}
-
-static inline void yuv2rgb15(int *blk, unsigned short *image) {
- int x, y;
- int *Yblk = blk + DSIZE2 * 2;
- int *Crblk = blk;
- int *Cbblk = blk + DSIZE2;
-
- if (!Config.Mdec) {
- for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 24) {
- if (y == 8) Yblk += DSIZE2;
- for (x = 0; x < 4; x++, image += 2, Crblk++, Cbblk++, Yblk += 2) {
- putquadrgb15(image, Yblk, *Crblk, *Cbblk);
- putquadrgb15(image + 8, Yblk + DSIZE2, *(Crblk + 4), *(Cbblk + 4));
- }
- }
- } else {
- for (y = 0; y < 16; y++, Yblk += 8, image += 16) {
- if (y == 8) Yblk += DSIZE2;
- putlinebw15(image, Yblk);
- putlinebw15(image + 8, Yblk + DSIZE2);
- }
- }
-}
-
-static inline void putlinebw24(u8 * image, int *Yblk) {
- int i;
- unsigned char Y;
- for (i = 0; i < 8 * 3; i += 3, Yblk++) {
- Y = CLAMP8(*Yblk);
- image[i + 0] = Y;
- image[i + 1] = Y;
- image[i + 2] = Y;
- }
-}
-
-static inline void putquadrgb24(u8 * image, int *Yblk, int Cr, int Cb) {
- int Y, R, G, B;
-
- R = MULR(Cr);
- G = MULG2(Cb,Cr);
- B = MULB(Cb);
-
- Y = MULY(Yblk[0]);
- image[0 * 3 + 0] = CLAMP_SCALE8(Y + R);
- image[0 * 3 + 1] = CLAMP_SCALE8(Y + G);
- image[0 * 3 + 2] = CLAMP_SCALE8(Y + B);
- Y = MULY(Yblk[1]);
- image[1 * 3 + 0] = CLAMP_SCALE8(Y + R);
- image[1 * 3 + 1] = CLAMP_SCALE8(Y + G);
- image[1 * 3 + 2] = CLAMP_SCALE8(Y + B);
- Y = MULY(Yblk[8]);
- image[16 * 3 + 0] = CLAMP_SCALE8(Y + R);
- image[16 * 3 + 1] = CLAMP_SCALE8(Y + G);
- image[16 * 3 + 2] = CLAMP_SCALE8(Y + B);
- Y = MULY(Yblk[9]);
- image[17 * 3 + 0] = CLAMP_SCALE8(Y + R);
- image[17 * 3 + 1] = CLAMP_SCALE8(Y + G);
- image[17 * 3 + 2] = CLAMP_SCALE8(Y + B);
-}
-
-static void yuv2rgb24(int *blk, u8 *image) {
- int x, y;
- int *Yblk = blk + DSIZE2 * 2;
- int *Crblk = blk;
- int *Cbblk = blk + DSIZE2;
-
- if (!Config.Mdec) {
- for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 8 * 3 * 3) {
- if (y == 8) Yblk += DSIZE2;
- for (x = 0; x < 4; x++, image += 6, Crblk++, Cbblk++, Yblk += 2) {
- putquadrgb24(image, Yblk, *Crblk, *Cbblk);
- putquadrgb24(image + 8 * 3, Yblk + DSIZE2, *(Crblk + 4), *(Cbblk + 4));
- }
- }
- } else {
- for (y = 0; y < 16; y++, Yblk += 8, image += 16 * 3) {
- if (y == 8) Yblk += DSIZE2;
- putlinebw24(image, Yblk);
- putlinebw24(image + 8 * 3, Yblk + DSIZE2);
- }
- }
-}
-
-void mdecInit(void) {
- memset(&mdec, 0, sizeof(mdec));
- memset(iq_y, 0, sizeof(iq_y));
- memset(iq_uv, 0, sizeof(iq_uv));
- mdec.rl = (u16 *)&psxM[0x100000];
-}
-
-// command register
-void mdecWrite0(u32 data) {
- mdec.reg0 = data;
-}
-
-u32 mdecRead0(void) {
- return mdec.reg0;
-}
-
-// status register
-void mdecWrite1(u32 data) {
- if (data & MDEC1_RESET) { // mdec reset
- mdec.reg0 = 0;
- mdec.reg1 = 0;
- mdec.pending_dma1.adr = 0;
- mdec.block_buffer_pos = 0;
- }
-}
-
-u32 mdecRead1(void) {
- u32 v = mdec.reg1;
- return v;
-}
-
-void psxDma0(u32 adr, u32 bcr, u32 chcr) {
- int cmd = mdec.reg0;
- int size;
-
- if (chcr != 0x01000201) {
- return;
- }
-
- /* mdec is STP till dma0 is released */
- mdec.reg1 |= MDEC1_STP;
-
- size = (bcr >> 16) * (bcr & 0xffff);
-
- switch (cmd >> 28) {
- case 0x3: // decode
- mdec.rl = (u16 *) PSXM(adr);
- /* now the mdec is busy till all data are decoded */
- mdec.reg1 |= MDEC1_BUSY;
- /* detect the end of decoding */
- mdec.rl_end = mdec.rl + (size * 2);
-
- /* sanity check */
- if(mdec.rl_end <= mdec.rl) {
- MDECINDMA_INT( size / 4 );
- return;
- }
-
- /* process the pending dma1 */
- if(mdec.pending_dma1.adr){
- psxDma1(mdec.pending_dma1.adr, mdec.pending_dma1.bcr, mdec.pending_dma1.chcr);
- }
- mdec.pending_dma1.adr = 0;
- return;
-
-
- case 0x4: // quantization table upload
- {
- u8 *p = (u8 *)PSXM(adr);
- // printf("uploading new quantization table\n");
- // printmatrixu8(p);
- // printmatrixu8(p + 64);
- iqtab_init(iq_y, p);
- iqtab_init(iq_uv, p + 64);
- }
-
- MDECINDMA_INT( size / 4 );
- return;
-
- case 0x6: // cosine table
- // printf("mdec cosine table\n");
-
- MDECINDMA_INT( size / 4 );
- return;
-
- default:
- // printf("mdec unknown command\n");
- break;
- }
-
- HW_DMA0_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(0);
-}
-
-void mdec0Interrupt()
-{
- HW_DMA0_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(0);
-}
-
-#define SIZE_OF_24B_BLOCK (16*16*3)
-#define SIZE_OF_16B_BLOCK (16*16*2)
-
-void psxDma1(u32 adr, u32 bcr, u32 chcr) {
- int blk[DSIZE2 * 6];
- u8 * image;
- int size;
- int dmacnt;
-
- if (chcr != 0x01000200) return;
-
- size = (bcr >> 16) * (bcr & 0xffff);
- /* size in byte */
- size *= 4;
- /* I guess the memory speed is limitating */
- dmacnt = size;
-
- if (!(mdec.reg1 & MDEC1_BUSY)) {
- /* add to pending */
- mdec.pending_dma1.adr = adr;
- mdec.pending_dma1.bcr = bcr;
- mdec.pending_dma1.chcr = chcr;
- /* do not free the dma */
- } else {
-
- image = (u8 *)PSXM(adr);
-
- if (mdec.reg0 & MDEC0_RGB24) {
- /* 16 bits decoding
- * block are 16 px * 16 px, each px are 2 byte
- */
-
- /* there is some partial block pending ? */
- if(mdec.block_buffer_pos != 0) {
- int n = mdec.block_buffer - mdec.block_buffer_pos + SIZE_OF_16B_BLOCK;
- /* TODO: check if partial block do not larger than size */
- memcpy(image, mdec.block_buffer_pos, n);
- image += n;
- size -= n;
- mdec.block_buffer_pos = 0;
- }
-
- while(size >= SIZE_OF_16B_BLOCK) {
- mdec.rl = rl2blk(blk, mdec.rl);
- yuv2rgb15(blk, (u16 *)image);
- image += SIZE_OF_16B_BLOCK;
- size -= SIZE_OF_16B_BLOCK;
- }
-
- if(size != 0) {
- mdec.rl = rl2blk(blk, mdec.rl);
- yuv2rgb15(blk, (u16 *)mdec.block_buffer);
- memcpy(image, mdec.block_buffer, size);
- mdec.block_buffer_pos = mdec.block_buffer + size;
- }
-
- } else {
- /* 24 bits decoding
- * block are 16 px * 16 px, each px are 3 byte
- */
-
- /* there is some partial block pending ? */
- if(mdec.block_buffer_pos != 0) {
- int n = mdec.block_buffer - mdec.block_buffer_pos + SIZE_OF_24B_BLOCK;
- /* TODO: check if partial block do not larger than size */
- memcpy(image, mdec.block_buffer_pos, n);
- image += n;
- size -= n;
- mdec.block_buffer_pos = 0;
- }
-
- while(size >= SIZE_OF_24B_BLOCK) {
- mdec.rl = rl2blk(blk, mdec.rl);
- yuv2rgb24(blk, image);
- image += SIZE_OF_24B_BLOCK;
- size -= SIZE_OF_24B_BLOCK;
- }
-
- if(size != 0) {
- mdec.rl = rl2blk(blk, mdec.rl);
- yuv2rgb24(blk, mdec.block_buffer);
- memcpy(image, mdec.block_buffer, size);
- mdec.block_buffer_pos = mdec.block_buffer + size;
- }
- }
-
- /* define the power of mdec */
- MDECOUTDMA_INT((int) ((dmacnt* MDEC_BIAS)));
- }
-}
-
-void mdec1Interrupt() {
- /* Author : gschwind
- *
- * in that case we have done all decoding stuff
- * Note that : each block end with 0xfe00 flags
- * the list of blocks end with the same 0xfe00 flags
- * data loock like :
- *
- * data block ...
- * 0xfe00
- * data block ...
- * 0xfe00
- * a lost of block ..
- *
- * 0xfe00
- * the last block
- * 0xfe00
- * 0xfe00
- *
- * OR
- *
- * if the 0xfe00 is not present the data size is important.
- *
- */
-
- /* this else if avoid to read outside memory */
- if(mdec.rl >= mdec.rl_end) {
- mdec.reg1 &= ~MDEC1_STP;
- HW_DMA0_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(0);
- mdec.reg1 &= ~MDEC1_BUSY;
- } else if (SWAP16(*(mdec.rl)) == MDEC_END_OF_DATA) {
- mdec.reg1 &= ~MDEC1_STP;
- HW_DMA0_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(0);
- mdec.reg1 &= ~MDEC1_BUSY;
- }
-
- HW_DMA1_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(1);
- return;
-}
-
-int mdecFreeze(gzFile f, int Mode) {
- gzfreeze(&mdec, sizeof(mdec));
- gzfreeze(iq_y, sizeof(iq_y));
- gzfreeze(iq_uv, sizeof(iq_uv));
-
- return 0;
-}
+/*************************************************************************** + * Copyright (C) 2010 Gabriele Gorla * + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#include "mdec.h" + +/* memory speed is 1 byte per MDEC_BIAS psx clock + * That mean (PSXCLK / MDEC_BIAS) B/s + * MDEC_BIAS = 2.0 => ~16MB/s + * MDEC_BIAS = 3.0 => ~11MB/s + * and so on ... + * I guess I have 50 images in 50Hz ... (could be 25 images ?) + * 320x240x24@50Hz => 11.52 MB/s + * 320x240x24@60Hz => 13.824 MB/s + * 320x240x16@50Hz => 7.68 MB/s + * 320x240x16@60Hz => 9.216 MB/s + * so 2.0 to 4.0 should be fine. + */ +#define MDEC_BIAS 2.0f + +#define DSIZE 8 +#define DSIZE2 (DSIZE * DSIZE) + +#define SCALE(x, n) ((x) >> (n)) +#define SCALER(x, n) (((x) + ((1 << (n)) >> 1)) >> (n)) + +#define AAN_CONST_BITS 12 +#define AAN_PRESCALE_BITS 16 + +#define AAN_CONST_SIZE 24 +#define AAN_CONST_SCALE (AAN_CONST_SIZE - AAN_CONST_BITS) + +#define AAN_PRESCALE_SIZE 20 +#define AAN_PRESCALE_SCALE (AAN_PRESCALE_SIZE-AAN_PRESCALE_BITS) +#define AAN_EXTRA 12 + +#define FIX_1_082392200 SCALER(18159528, AAN_CONST_SCALE) // B6 +#define FIX_1_414213562 SCALER(23726566, AAN_CONST_SCALE) // A4 +#define FIX_1_847759065 SCALER(31000253, AAN_CONST_SCALE) // A2 +#define FIX_2_613125930 SCALER(43840978, AAN_CONST_SCALE) // B2 + +#define MULS(var, const) (SCALE((var) * (const), AAN_CONST_BITS)) + +#define RLE_RUN(a) ((a) >> 10) +#define RLE_VAL(a) (((int)(a) << (sizeof(int) * 8 - 10)) >> (sizeof(int) * 8 - 10)) + +#if 0 +static void printmatrixu8(u8 *m) { + int i; + for(i = 0; i < DSIZE2; i++) { + printf("%3d ",m[i]); + if((i+1) % 8 == 0) printf("\n"); + } +} +#endif + +static inline void fillcol(int *blk, int val) { + blk[0 * DSIZE] = blk[1 * DSIZE] = blk[2 * DSIZE] = blk[3 * DSIZE] + = blk[4 * DSIZE] = blk[5 * DSIZE] = blk[6 * DSIZE] = blk[7 * DSIZE] = val; +} + +static inline void fillrow(int *blk, int val) { + blk[0] = blk[1] = blk[2] = blk[3] + = blk[4] = blk[5] = blk[6] = blk[7] = val; +} + +void idct(int *block,int used_col) { + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int z5, z10, z11, z12, z13; + int *ptr; + int i; + + // the block has only the DC coefficient + if (used_col == -1) { + int v = block[0]; + for (i = 0; i < DSIZE2; i++) block[i] = v; + return; + } + + // last_col keeps track of the highest column with non zero coefficients + ptr = block; + for (i = 0; i < DSIZE; i++, ptr++) { + if ((used_col & (1 << i)) == 0) { + // the column is empty or has only the DC coefficient + if (ptr[DSIZE * 0]) { + fillcol(ptr, ptr[0]); + used_col |= (1 << i); + } + continue; + } + + // further optimization could be made by keeping track of + // last_row in rl2blk + z10 = ptr[DSIZE * 0] + ptr[DSIZE * 4]; // s04 + z11 = ptr[DSIZE * 0] - ptr[DSIZE * 4]; // d04 + z13 = ptr[DSIZE * 2] + ptr[DSIZE * 6]; // s26 + z12 = MULS(ptr[DSIZE * 2] - ptr[DSIZE * 6], FIX_1_414213562) - z13; + //^^^^ d26=d26*2*A4-s26 + + tmp0 = z10 + z13; // os07 = s04 + s26 + tmp3 = z10 - z13; // os34 = s04 - s26 + tmp1 = z11 + z12; // os16 = d04 + d26 + tmp2 = z11 - z12; // os25 = d04 - d26 + + z13 = ptr[DSIZE * 3] + ptr[DSIZE * 5]; //s53 + z10 = ptr[DSIZE * 3] - ptr[DSIZE * 5]; //-d53 + z11 = ptr[DSIZE * 1] + ptr[DSIZE * 7]; //s17 + z12 = ptr[DSIZE * 1] - ptr[DSIZE * 7]; //d17 + + tmp7 = z11 + z13; // od07 = s17 + s53 + + z5 = (z12 - z10) * (FIX_1_847759065); + tmp6 = SCALE(z10*(FIX_2_613125930) + z5, AAN_CONST_BITS) - tmp7; + tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6; + tmp4 = SCALE(z12*(FIX_1_082392200) - z5, AAN_CONST_BITS) + tmp5; + + // path #1 + //z5 = (z12 - z10)* FIX_1_847759065; + // tmp0 = (d17 + d53) * 2*A2 + + //tmp6 = DESCALE(z10*FIX_2_613125930 + z5, CONST_BITS) - tmp7; + // od16 = (d53*-2*B2 + tmp0) - od07 + + //tmp4 = DESCALE(z12*FIX_1_082392200 - z5, CONST_BITS) + tmp5; + // od34 = (d17*2*B6 - tmp0) + od25 + + // path #2 + + // od34 = d17*2*(B6-A2) - d53*2*A2 + // od16 = d53*2*(A2-B2) + d17*2*A2 + + // end + + // tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6; + // od25 = (s17 - s53)*2*A4 - od16 + + ptr[DSIZE * 0] = (tmp0 + tmp7); // os07 + od07 + ptr[DSIZE * 7] = (tmp0 - tmp7); // os07 - od07 + ptr[DSIZE * 1] = (tmp1 + tmp6); // os16 + od16 + ptr[DSIZE * 6] = (tmp1 - tmp6); // os16 - od16 + ptr[DSIZE * 2] = (tmp2 + tmp5); // os25 + od25 + ptr[DSIZE * 5] = (tmp2 - tmp5); // os25 - od25 + ptr[DSIZE * 4] = (tmp3 + tmp4); // os34 + od34 + ptr[DSIZE * 3] = (tmp3 - tmp4); // os34 - od34 + } + + ptr = block; + if (used_col == 1) { + for (i = 0; i < DSIZE; i++) + fillrow(block + DSIZE * i, block[DSIZE * i]); + } else { + for (i = 0; i < DSIZE; i++, ptr += DSIZE) { + z10 = ptr[0] + ptr[4]; + z11 = ptr[0] - ptr[4]; + z13 = ptr[2] + ptr[6]; + z12 = MULS(ptr[2] - ptr[6], FIX_1_414213562) - z13; + + tmp0 = z10 + z13; + tmp3 = z10 - z13; + tmp1 = z11 + z12; + tmp2 = z11 - z12; + + z13 = ptr[3] + ptr[5]; + z10 = ptr[3] - ptr[5]; + z11 = ptr[1] + ptr[7]; + z12 = ptr[1] - ptr[7]; + + tmp7 = z11 + z13; + z5 = (z12 - z10) * FIX_1_847759065; + tmp6 = SCALE(z10 * FIX_2_613125930 + z5, AAN_CONST_BITS) - tmp7; + tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6; + tmp4 = SCALE(z12 * FIX_1_082392200 - z5, AAN_CONST_BITS) + tmp5; + + ptr[0] = tmp0 + tmp7; + + ptr[7] = tmp0 - tmp7; + ptr[1] = tmp1 + tmp6; + ptr[6] = tmp1 - tmp6; + ptr[2] = tmp2 + tmp5; + ptr[5] = tmp2 - tmp5; + ptr[4] = tmp3 + tmp4; + ptr[3] = tmp3 - tmp4; + } + } +} + +// mdec0: command register +#define MDEC0_STP 0x02000000 +#define MDEC0_RGB24 0x08000000 +#define MDEC0_SIZE_MASK 0x0000FFFF + +// mdec1: status register +#define MDEC1_BUSY 0x20000000 +#define MDEC1_DREQ 0x18000000 +#define MDEC1_FIFO 0xc0000000 +#define MDEC1_RGB24 0x02000000 +#define MDEC1_STP 0x00800000 +#define MDEC1_RESET 0x80000000 + +struct _pending_dma1 { + u32 adr; + u32 bcr; + u32 chcr; +}; + +static struct { + u32 reg0; + u32 reg1; + u16 * rl; + u16 * rl_end; + u8 * block_buffer_pos; + u8 block_buffer[16*16*3]; + struct _pending_dma1 pending_dma1; +} mdec; + +static int iq_y[DSIZE2], iq_uv[DSIZE2]; + +static int zscan[DSIZE2] = { + 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[DSIZE2] = { + 1048576, 1454417, 1370031, 1232995, 1048576, 823861, 567485, 289301, + 1454417, 2017334, 1900287, 1710213, 1454417, 1142728, 787125, 401273, + 1370031, 1900287, 1790031, 1610986, 1370031, 1076426, 741455, 377991, + 1232995, 1710213, 1610986, 1449849, 1232995, 968758, 667292, 340183, + 1048576, 1454417, 1370031, 1232995, 1048576, 823861, 567485, 289301, + 823861, 1142728, 1076426, 968758, 823861, 647303, 445870, 227303, + 567485, 787125, 741455, 667292, 567485, 445870, 307121, 156569, + 289301, 401273, 377991, 340183, 289301, 227303, 156569, 79818 +}; + +static void iqtab_init(int *iqtab, unsigned char *iq_y) { + int i; + + for (i = 0; i < DSIZE2; i++) { + iqtab[i] = (iq_y[i] * SCALER(aanscales[zscan[i]], AAN_PRESCALE_SCALE)); + } +} + +#define MDEC_END_OF_DATA 0xfe00 + +unsigned short *rl2blk(int *blk, unsigned short *mdec_rl) { + int i, k, q_scale, rl, used_col; + int *iqtab; + + memset(blk, 0, 6 * DSIZE2 * sizeof(int)); + iqtab = iq_uv; + for (i = 0; i < 6; i++) { + // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4) + if (i == 2) iqtab = iq_y; + + rl = SWAP16(*mdec_rl); mdec_rl++; + q_scale = RLE_RUN(rl); + blk[0] = SCALER(iqtab[0] * RLE_VAL(rl), AAN_EXTRA - 3); + for (k = 0, used_col = 0;;) { + rl = SWAP16(*mdec_rl); mdec_rl++; + if (rl == MDEC_END_OF_DATA) break; + k += RLE_RUN(rl) + 1; // skip zero-coefficients + + if (k > 63) { + // printf("run lenght exceeded 64 enties\n"); + break; + } + + // zigzag transformation + blk[zscan[k]] = SCALER(RLE_VAL(rl) * iqtab[k] * q_scale, AAN_EXTRA); + // keep track of used columns to speed up the idtc + used_col |= (zscan[k] > 7) ? 1 << (zscan[k] & 7) : 0; + } + + if (k == 0) used_col = -1; + // used_col is -1 for blocks with only the DC coefficient + // any other value is a bitmask of the columns that have + // at least one non zero cofficient in the rows 1-7 + // single coefficients in row 0 are treted specially + // in the idtc function + idct(blk, used_col); + blk += DSIZE2; + } + return mdec_rl; +} + +// full scale (JPEG) +// Y/Cb/Cr[0...255] -> R/G/B[0...255] +// R = 1.000 * (Y) + 1.400 * (Cr - 128) +// G = 1.000 * (Y) - 0.343 * (Cb - 128) - 0.711 (Cr - 128) +// B = 1.000 * (Y) + 1.765 * (Cb - 128) +#define MULR(a) ((1434 * (a))) +#define MULB(a) ((1807 * (a))) +#define MULG2(a, b) ((-351 * (a) - 728 * (b))) +#define MULY(a) ((a) << 10) + +#define MAKERGB15(r, g, b, a) (SWAP16(a | ((b) << 10) | ((g) << 5) | (r))) +#define SCALE8(c) SCALER(c, 20) +#define SCALE5(c) SCALER(c, 23) + +#define CLAMP5(c) ( ((c) < -16) ? 0 : (((c) > (31 - 16)) ? 31 : ((c) + 16)) ) +#define CLAMP8(c) ( ((c) < -128) ? 0 : (((c) > (255 - 128)) ? 255 : ((c) + 128)) ) + +#define CLAMP_SCALE8(a) (CLAMP8(SCALE8(a))) +#define CLAMP_SCALE5(a) (CLAMP5(SCALE5(a))) + +static inline void putlinebw15(u16 *image, int *Yblk) { + int i; + int A = (mdec.reg0 & MDEC0_STP) ? 0x8000 : 0; + + for (i = 0; i < 8; i++, Yblk++) { + int Y = *Yblk; + // missing rounding + image[i] = SWAP16((CLAMP5(Y >> 3) * 0x421) | A); + } +} + +static inline void putquadrgb15(u16 *image, int *Yblk, int Cr, int Cb) { + int Y, R, G, B; + int A = (mdec.reg0 & MDEC0_STP) ? 0x8000 : 0; + R = MULR(Cr); + G = MULG2(Cb, Cr); + B = MULB(Cb); + + // added transparency + Y = MULY(Yblk[0]); + image[0] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A); + Y = MULY(Yblk[1]); + image[1] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A); + Y = MULY(Yblk[8]); + image[16] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A); + Y = MULY(Yblk[9]); + image[17] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A); +} + +static inline void yuv2rgb15(int *blk, unsigned short *image) { + int x, y; + int *Yblk = blk + DSIZE2 * 2; + int *Crblk = blk; + int *Cbblk = blk + DSIZE2; + + if (!Config.Mdec) { + for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 24) { + if (y == 8) Yblk += DSIZE2; + for (x = 0; x < 4; x++, image += 2, Crblk++, Cbblk++, Yblk += 2) { + putquadrgb15(image, Yblk, *Crblk, *Cbblk); + putquadrgb15(image + 8, Yblk + DSIZE2, *(Crblk + 4), *(Cbblk + 4)); + } + } + } else { + for (y = 0; y < 16; y++, Yblk += 8, image += 16) { + if (y == 8) Yblk += DSIZE2; + putlinebw15(image, Yblk); + putlinebw15(image + 8, Yblk + DSIZE2); + } + } +} + +static inline void putlinebw24(u8 * image, int *Yblk) { + int i; + unsigned char Y; + for (i = 0; i < 8 * 3; i += 3, Yblk++) { + Y = CLAMP8(*Yblk); + image[i + 0] = Y; + image[i + 1] = Y; + image[i + 2] = Y; + } +} + +static inline void putquadrgb24(u8 * image, int *Yblk, int Cr, int Cb) { + int Y, R, G, B; + + R = MULR(Cr); + G = MULG2(Cb,Cr); + B = MULB(Cb); + + Y = MULY(Yblk[0]); + image[0 * 3 + 0] = CLAMP_SCALE8(Y + R); + image[0 * 3 + 1] = CLAMP_SCALE8(Y + G); + image[0 * 3 + 2] = CLAMP_SCALE8(Y + B); + Y = MULY(Yblk[1]); + image[1 * 3 + 0] = CLAMP_SCALE8(Y + R); + image[1 * 3 + 1] = CLAMP_SCALE8(Y + G); + image[1 * 3 + 2] = CLAMP_SCALE8(Y + B); + Y = MULY(Yblk[8]); + image[16 * 3 + 0] = CLAMP_SCALE8(Y + R); + image[16 * 3 + 1] = CLAMP_SCALE8(Y + G); + image[16 * 3 + 2] = CLAMP_SCALE8(Y + B); + Y = MULY(Yblk[9]); + image[17 * 3 + 0] = CLAMP_SCALE8(Y + R); + image[17 * 3 + 1] = CLAMP_SCALE8(Y + G); + image[17 * 3 + 2] = CLAMP_SCALE8(Y + B); +} + +static void yuv2rgb24(int *blk, u8 *image) { + int x, y; + int *Yblk = blk + DSIZE2 * 2; + int *Crblk = blk; + int *Cbblk = blk + DSIZE2; + + if (!Config.Mdec) { + for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 8 * 3 * 3) { + if (y == 8) Yblk += DSIZE2; + for (x = 0; x < 4; x++, image += 6, Crblk++, Cbblk++, Yblk += 2) { + putquadrgb24(image, Yblk, *Crblk, *Cbblk); + putquadrgb24(image + 8 * 3, Yblk + DSIZE2, *(Crblk + 4), *(Cbblk + 4)); + } + } + } else { + for (y = 0; y < 16; y++, Yblk += 8, image += 16 * 3) { + if (y == 8) Yblk += DSIZE2; + putlinebw24(image, Yblk); + putlinebw24(image + 8 * 3, Yblk + DSIZE2); + } + } +} + +void mdecInit(void) { + memset(&mdec, 0, sizeof(mdec)); + memset(iq_y, 0, sizeof(iq_y)); + memset(iq_uv, 0, sizeof(iq_uv)); + mdec.rl = (u16 *)&psxM[0x100000]; +} + +// command register +void mdecWrite0(u32 data) { + mdec.reg0 = data; +} + +u32 mdecRead0(void) { + return mdec.reg0; +} + +// status register +void mdecWrite1(u32 data) { + if (data & MDEC1_RESET) { // mdec reset + mdec.reg0 = 0; + mdec.reg1 = 0; + mdec.pending_dma1.adr = 0; + mdec.block_buffer_pos = 0; + } +} + +u32 mdecRead1(void) { + u32 v = mdec.reg1; + return v; +} + +void psxDma0(u32 adr, u32 bcr, u32 chcr) { + int cmd = mdec.reg0; + int size; + + if (chcr != 0x01000201) { + return; + } + + /* mdec is STP till dma0 is released */ + mdec.reg1 |= MDEC1_STP; + + size = (bcr >> 16) * (bcr & 0xffff); + + switch (cmd >> 28) { + case 0x3: // decode + mdec.rl = (u16 *) PSXM(adr); + /* now the mdec is busy till all data are decoded */ + mdec.reg1 |= MDEC1_BUSY; + /* detect the end of decoding */ + mdec.rl_end = mdec.rl + (size * 2); + + /* sanity check */ + if(mdec.rl_end <= mdec.rl) { + MDECINDMA_INT( size / 4 ); + return; + } + + /* process the pending dma1 */ + if(mdec.pending_dma1.adr){ + psxDma1(mdec.pending_dma1.adr, mdec.pending_dma1.bcr, mdec.pending_dma1.chcr); + } + mdec.pending_dma1.adr = 0; + return; + + + case 0x4: // quantization table upload + { + u8 *p = (u8 *)PSXM(adr); + // printf("uploading new quantization table\n"); + // printmatrixu8(p); + // printmatrixu8(p + 64); + iqtab_init(iq_y, p); + iqtab_init(iq_uv, p + 64); + } + + MDECINDMA_INT( size / 4 ); + return; + + case 0x6: // cosine table + // printf("mdec cosine table\n"); + + MDECINDMA_INT( size / 4 ); + return; + + default: + // printf("mdec unknown command\n"); + break; + } + + HW_DMA0_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(0); +} + +void mdec0Interrupt() +{ + HW_DMA0_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(0); +} + +#define SIZE_OF_24B_BLOCK (16*16*3) +#define SIZE_OF_16B_BLOCK (16*16*2) + +void psxDma1(u32 adr, u32 bcr, u32 chcr) { + int blk[DSIZE2 * 6]; + u8 * image; + int size; + int dmacnt; + + if (chcr != 0x01000200) return; + + size = (bcr >> 16) * (bcr & 0xffff); + /* size in byte */ + size *= 4; + /* I guess the memory speed is limitating */ + dmacnt = size; + + if (!(mdec.reg1 & MDEC1_BUSY)) { + /* add to pending */ + mdec.pending_dma1.adr = adr; + mdec.pending_dma1.bcr = bcr; + mdec.pending_dma1.chcr = chcr; + /* do not free the dma */ + } else { + + image = (u8 *)PSXM(adr); + + if (mdec.reg0 & MDEC0_RGB24) { + /* 16 bits decoding + * block are 16 px * 16 px, each px are 2 byte + */ + + /* there is some partial block pending ? */ + if(mdec.block_buffer_pos != 0) { + int n = mdec.block_buffer - mdec.block_buffer_pos + SIZE_OF_16B_BLOCK; + /* TODO: check if partial block do not larger than size */ + memcpy(image, mdec.block_buffer_pos, n); + image += n; + size -= n; + mdec.block_buffer_pos = 0; + } + + while(size >= SIZE_OF_16B_BLOCK) { + mdec.rl = rl2blk(blk, mdec.rl); + yuv2rgb15(blk, (u16 *)image); + image += SIZE_OF_16B_BLOCK; + size -= SIZE_OF_16B_BLOCK; + } + + if(size != 0) { + mdec.rl = rl2blk(blk, mdec.rl); + yuv2rgb15(blk, (u16 *)mdec.block_buffer); + memcpy(image, mdec.block_buffer, size); + mdec.block_buffer_pos = mdec.block_buffer + size; + } + + } else { + /* 24 bits decoding + * block are 16 px * 16 px, each px are 3 byte + */ + + /* there is some partial block pending ? */ + if(mdec.block_buffer_pos != 0) { + int n = mdec.block_buffer - mdec.block_buffer_pos + SIZE_OF_24B_BLOCK; + /* TODO: check if partial block do not larger than size */ + memcpy(image, mdec.block_buffer_pos, n); + image += n; + size -= n; + mdec.block_buffer_pos = 0; + } + + while(size >= SIZE_OF_24B_BLOCK) { + mdec.rl = rl2blk(blk, mdec.rl); + yuv2rgb24(blk, image); + image += SIZE_OF_24B_BLOCK; + size -= SIZE_OF_24B_BLOCK; + } + + if(size != 0) { + mdec.rl = rl2blk(blk, mdec.rl); + yuv2rgb24(blk, mdec.block_buffer); + memcpy(image, mdec.block_buffer, size); + mdec.block_buffer_pos = mdec.block_buffer + size; + } + } + + /* define the power of mdec */ + MDECOUTDMA_INT((int) ((dmacnt* MDEC_BIAS))); + } +} + +void mdec1Interrupt() { + /* Author : gschwind + * + * in that case we have done all decoding stuff + * Note that : each block end with 0xfe00 flags + * the list of blocks end with the same 0xfe00 flags + * data loock like : + * + * data block ... + * 0xfe00 + * data block ... + * 0xfe00 + * a lost of block .. + * + * 0xfe00 + * the last block + * 0xfe00 + * 0xfe00 + * + * OR + * + * if the 0xfe00 is not present the data size is important. + * + */ + + /* this else if avoid to read outside memory */ + if(mdec.rl >= mdec.rl_end) { + mdec.reg1 &= ~MDEC1_STP; + HW_DMA0_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(0); + mdec.reg1 &= ~MDEC1_BUSY; + } else if (SWAP16(*(mdec.rl)) == MDEC_END_OF_DATA) { + mdec.reg1 &= ~MDEC1_STP; + HW_DMA0_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(0); + mdec.reg1 &= ~MDEC1_BUSY; + } + + HW_DMA1_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(1); + return; +} + +int mdecFreeze(gzFile f, int Mode) { + gzfreeze(&mdec, sizeof(mdec)); + gzfreeze(iq_y, sizeof(iq_y)); + gzfreeze(iq_uv, sizeof(iq_uv)); + + return 0; +} diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c index 1de0aff8..297b1367 100644..100755 --- a/libpcsxcore/misc.c +++ b/libpcsxcore/misc.c @@ -1,749 +1,749 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* Miscellaneous functions, including savestates and CD-ROM loading.
-*/
-
-#include "misc.h"
-#include "cdrom.h"
-#include "mdec.h"
-#include "ppf.h"
-
-char CdromId[10] = "";
-char CdromLabel[33] = "";
-
-// PSX Executable types
-#define PSX_EXE 1
-#define CPE_EXE 2
-#define COFF_EXE 3
-#define INVALID_EXE 4
-
-#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];
-};
-
-void mmssdd( char *b, char *p )
-{
- int m, s, d;
-#if defined(__BIGENDIAN__)
- int block = (b[0] & 0xff) | ((b[1] & 0xff) << 8) | ((b[2] & 0xff) << 16) | (b[3] << 24);
-#else
- int block = *((int*)b);
-#endif
-
- block += 150;
- m = block / 4500; // minutes
- block = block - m * 4500; // minutes rest
- s = block / 75; // seconds
- d = block - s * 75; // seconds rest
-
- m = ((m / 10) << 4) | m % 10;
- s = ((s / 10) << 4) | s % 10;
- d = ((d / 10) << 4) | d % 10;
-
- p[0] = m;
- p[1] = s;
- p[2] = d;
-}
-
-#define incTime() \
- time[0] = btoi(time[0]); time[1] = btoi(time[1]); time[2] = btoi(time[2]); \
- time[2]++; \
- if(time[2] == 75) { \
- time[2] = 0; \
- time[1]++; \
- if (time[1] == 60) { \
- time[1] = 0; \
- time[0]++; \
- } \
- } \
- time[0] = itob(time[0]); time[1] = itob(time[1]); time[2] = itob(time[2]);
-
-#define READTRACK() \
- if (CDR_readTrack(time) == -1) return -1; \
- buf = CDR_getBuffer(); \
- if (buf == NULL) return -1; else CheckPPFCache(buf, time[0], time[1], time[2]);
-
-#define READDIR(_dir) \
- READTRACK(); \
- memcpy(_dir, buf + 12, 2048); \
- \
- incTime(); \
- READTRACK(); \
- memcpy(_dir + 2048, buf + 12, 2048);
-
-int GetCdromFile(u8 *mdir, u8 *time, s8 *filename) {
- struct iso_directory_record *dir;
- char ddir[4096];
- u8 *buf;
- int i;
-
- // only try to scan if a filename is given
- if (!strlen(filename)) return -1;
-
- i = 0;
- while (i < 4096) {
- dir = (struct iso_directory_record*) &mdir[i];
- if (dir->length[0] == 0) {
- return -1;
- }
- i += dir->length[0];
-
- if (dir->flags[0] & 0x2) { // it's a dir
- if (!strnicmp((char *)&dir->name[0], filename, dir->name_len[0])) {
- if (filename[dir->name_len[0]] != '\\') continue;
-
- filename += dir->name_len[0] + 1;
-
- mmssdd(dir->extent, (char *)time);
- READDIR(ddir);
- i = 0;
- mdir = ddir;
- }
- } else {
- if (!strnicmp((char *)&dir->name[0], filename, strlen(filename))) {
- mmssdd(dir->extent, (char *)time);
- break;
- }
- }
- }
- return 0;
-}
-
-int LoadCdrom() {
- EXE_HEADER tmpHead;
- struct iso_directory_record *dir;
- u8 time[4], *buf;
- u8 mdir[4096];
- s8 exename[256];
-
- if (!Config.HLE) {
- if (!Config.SlowBoot) psxRegs.pc = psxRegs.GPR.n.ra;
- return 0;
- }
-
- time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
-
- READTRACK();
-
- // skip head and sub, and go to the root directory record
- dir = (struct iso_directory_record*) &buf[12+156];
-
- mmssdd(dir->extent, (char*)time);
-
- READDIR(mdir);
-
- // Load SYSTEM.CNF and scan for the main executable
- if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") == -1) {
- // if SYSTEM.CNF is missing, start an existing PSX.EXE
- if (GetCdromFile(mdir, time, "PSX.EXE;1") == -1) return -1;
-
- READTRACK();
- }
- else {
- // read the SYSTEM.CNF
- READTRACK();
-
- sscanf((char *)buf + 12, "BOOT = cdrom:\\%256s", exename);
- if (GetCdromFile(mdir, time, exename) == -1) {
- sscanf((char *)buf + 12, "BOOT = cdrom:%256s", exename);
- if (GetCdromFile(mdir, time, exename) == -1) {
- char *ptr = strstr(buf + 12, "cdrom:");
- if (ptr != NULL) {
- ptr += 6;
- while (*ptr == '\\' || *ptr == '/') ptr++;
- strncpy(exename, ptr, 255);
- exename[255] = '\0';
- ptr = exename;
- while (*ptr != '\0' && *ptr != '\r' && *ptr != '\n') ptr++;
- *ptr = '\0';
- if (GetCdromFile(mdir, time, exename) == -1)
- return -1;
- } else
- return -1;
- }
- }
-
- // Read the EXE-Header
- READTRACK();
- }
-
- memcpy(&tmpHead, buf + 12, sizeof(EXE_HEADER));
-
- psxRegs.pc = SWAP32(tmpHead.pc0);
- psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
- psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
- if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00;
-
- tmpHead.t_size = SWAP32(tmpHead.t_size);
- tmpHead.t_addr = SWAP32(tmpHead.t_addr);
-
- // Read the rest of the main executable
- while (tmpHead.t_size) {
- void *ptr = (void *)PSXM(tmpHead.t_addr);
-
- incTime();
- READTRACK();
-
- if (ptr != NULL) memcpy(ptr, buf+12, 2048);
-
- tmpHead.t_size -= 2048;
- tmpHead.t_addr += 2048;
- }
-
- return 0;
-}
-
-int LoadCdromFile(const char *filename, EXE_HEADER *head) {
- struct iso_directory_record *dir;
- u8 time[4],*buf;
- u8 mdir[4096], exename[256];
- u32 size, addr;
-
- sscanf(filename, "cdrom:\\%256s", exename);
-
- time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
-
- READTRACK();
-
- // skip head and sub, and go to the root directory record
- dir = (struct iso_directory_record *)&buf[12 + 156];
-
- mmssdd(dir->extent, (char*)time);
-
- READDIR(mdir);
-
- if (GetCdromFile(mdir, time, exename) == -1) return -1;
-
- READTRACK();
-
- memcpy(head, buf + 12, sizeof(EXE_HEADER));
- size = head->t_size;
- addr = head->t_addr;
-
- while (size) {
- incTime();
- READTRACK();
-
- memcpy((void *)PSXM(addr), buf + 12, 2048);
-
- size -= 2048;
- addr += 2048;
- }
-
- return 0;
-}
-
-int CheckCdrom() {
- struct iso_directory_record *dir;
- unsigned char time[4], *buf;
- unsigned char mdir[4096];
- char exename[256];
- int i, c;
-
- FreePPFCache();
-
- time[0] = itob(0);
- time[1] = itob(2);
- time[2] = itob(0x10);
-
- READTRACK();
-
- CdromLabel[0] = '\0';
- CdromId[0] = '\0';
-
- strncpy(CdromLabel, buf + 52, 32);
-
- // skip head and sub, and go to the root directory record
- dir = (struct iso_directory_record *)&buf[12 + 156];
-
- mmssdd(dir->extent, (char *)time);
-
- READDIR(mdir);
-
- if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") != -1) {
- READTRACK();
-
- sscanf((char *)buf + 12, "BOOT = cdrom:\\%256s", exename);
- if (GetCdromFile(mdir, time, exename) == -1) {
- sscanf((char *)buf + 12, "BOOT = cdrom:%256s", exename);
- if (GetCdromFile(mdir, time, exename) == -1) {
- char *ptr = strstr(buf + 12, "cdrom:"); // possibly the executable is in some subdir
- if (ptr != NULL) {
- ptr += 6;
- while (*ptr == '\\' || *ptr == '/') ptr++;
- strncpy(exename, ptr, 255);
- exename[255] = '\0';
- ptr = exename;
- while (*ptr != '\0' && *ptr != '\r' && *ptr != '\n') ptr++;
- *ptr = '\0';
- if (GetCdromFile(mdir, time, exename) == -1)
- return -1; // main executable not found
- } else
- return -1;
- }
- }
- } else if (GetCdromFile(mdir, time, "PSX.EXE;1") != -1) {
- strcpy(exename, "PSX.EXE;1");
- strcpy(CdromId, "SLUS99999");
- } else
- return -1; // SYSTEM.CNF and PSX.EXE not found
-
- if (CdromId[0] == '\0') {
- i = strlen(exename);
- if (i >= 2) {
- if (exename[i - 2] == ';') i-= 2;
- c = 8; i--;
- while (i >= 0 && c >= 0) {
- if (isalnum(exename[i])) CdromId[c--] = exename[i];
- i--;
- }
- }
- }
-
- if (Config.PsxAuto) { // autodetect system (pal or ntsc)
- if((CdromId[2] == 'e') || (CdromId[2] == 'E') ||
- !strncmp(CdromId, "\0DTLS3035", 10) ||
- !strncmp(CdromId, "PBPX95001", 10) || // according to redump.org, these PAL
- !strncmp(CdromId, "PBPX95007", 10) || // discs have a non-standard ID;
- !strncmp(CdromId, "PBPX95008", 10)) // add more serials if they are discovered.
- Config.PsxType = PSX_TYPE_PAL; // pal
- else Config.PsxType = PSX_TYPE_NTSC; // ntsc
- }
-
- if (CdromLabel[0] == ' ') {
- strncpy(CdromLabel, CdromId, 9);
- }
- SysPrintf(_("CD-ROM Label: %.32s\n"), CdromLabel);
- SysPrintf(_("CD-ROM ID: %.9s\n"), CdromId);
-
- BuildPPFCache();
- LoadSBI();
-
- return 0;
-}
-
-static int PSXGetFileType(FILE *f) {
- unsigned long current;
- u8 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 (SWAPu16(coff_hdr->f_magic) == 0x0162)
- return COFF_EXE;
-
- return INVALID_EXE;
-}
-
-static void LoadLibPS() {
- char buf[MAXPATHLEN];
- FILE *f;
-
- // Load Net Yaroze runtime library (if exists)
- sprintf(buf, "%s/libps.exe", Config.BiosDir);
- f = fopen(buf, "rb");
-
- if (f != NULL) {
- fseek(f, 0x800, SEEK_SET);
- fread(psxM + 0x10000, 0x61000, 1, f);
- fclose(f);
- }
-}
-
-int Load(const char *ExePath) {
- FILE *tmpFile;
- EXE_HEADER tmpHead;
- FILHDR coffHead;
- AOUTHDR optHead;
- SCNHDR section;
- int type, i;
- int retval = 0;
- u8 opcode;
- u32 section_address, section_size;
-
- strncpy(CdromId, "SLUS99999", 9);
- strncpy(CdromLabel, "SLUS_999.99", 11);
-
- tmpFile = fopen(ExePath, "rb");
- if (tmpFile == NULL) {
- SysPrintf(_("Error opening file: %s.\n"), ExePath);
- retval = -1;
- } else {
- LoadLibPS();
-
- type = PSXGetFileType(tmpFile);
- switch (type) {
- case PSX_EXE:
- fread(&tmpHead, sizeof(EXE_HEADER), 1, tmpFile);
- fseek(tmpFile, 0x800, SEEK_SET);
- fread(PSXM(SWAP32(tmpHead.t_addr)), SWAP32(tmpHead.t_size), 1, tmpFile);
- fclose(tmpFile);
- psxRegs.pc = SWAP32(tmpHead.pc0);
- psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
- psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
- if (psxRegs.GPR.n.sp == 0)
- psxRegs.GPR.n.sp = 0x801fff00;
- retval = 0;
- break;
-
- case CPE_EXE:
- fseek(tmpFile, 6, SEEK_SET); /* Something tells me we should go to 4 and read the "08 00" here... */
- do {
- fread(&opcode, 1, 1, tmpFile);
- switch (opcode) {
- case 1: /* Section loading */
- fread(§ion_address, 4, 1, tmpFile);
- fread(§ion_size, 4, 1, tmpFile);
- section_address = SWAPu32(section_address);
- section_size = SWAPu32(section_size);
-#ifdef EMU_LOG
- EMU_LOG("Loading %08X bytes from %08X to %08X\n", section_size, ftell(tmpFile), section_address);
-#endif
- fread(PSXM(section_address), section_size, 1, tmpFile);
- break;
- case 3: /* register loading (PC only?) */
- fseek(tmpFile, 2, SEEK_CUR); /* unknown field */
- fread(&psxRegs.pc, 4, 1, tmpFile);
- psxRegs.pc = SWAPu32(psxRegs.pc);
- break;
- case 0: /* End of file */
- break;
- default:
- SysPrintf(_("Unknown CPE opcode %02x at position %08x.\n"), opcode, ftell(tmpFile) - 1);
- retval = -1;
- break;
- }
- } while (opcode != 0 && retval == 0);
- break;
-
- case COFF_EXE:
- fread(&coffHead, sizeof(coffHead), 1, tmpFile);
- fread(&optHead, sizeof(optHead), 1, tmpFile);
-
- psxRegs.pc = SWAP32(optHead.entry);
- psxRegs.GPR.n.sp = 0x801fff00;
-
- for (i = 0; i < SWAP16(coffHead.f_nscns); i++) {
- fseek(tmpFile, sizeof(FILHDR) + SWAP16(coffHead.f_opthdr) + sizeof(section) * i, SEEK_SET);
- fread(§ion, sizeof(section), 1, tmpFile);
-
- if (section.s_scnptr != 0) {
- fseek(tmpFile, SWAP32(section.s_scnptr), SEEK_SET);
- fread(PSXM(SWAP32(section.s_paddr)), SWAP32(section.s_size), 1, tmpFile);
- } else {
- memset(PSXM(SWAP32(section.s_paddr)), 0, SWAP32(section.s_size));
- }
- }
- break;
-
- case INVALID_EXE:
- SysPrintf(_("This file does not appear to be a valid PSX file.\n"));
- retval = -1;
- break;
- }
- }
-
- if (retval != 0) {
- CdromId[0] = '\0';
- CdromLabel[0] = '\0';
- }
-
- return retval;
-}
-
-// STATES
-
-static const char PcsxrHeader[32] = "STv4 PCSXR v" PACKAGE_VERSION;
-
-// Savestate Versioning!
-// If you make changes to the savestate version, please increment the value below.
-static const u32 SaveVersion = 0x8b410007;
-
-int SaveState(const char *file) {
- gzFile f;
- GPUFreeze_t *gpufP;
- SPUFreeze_t *spufP;
- int Size;
- unsigned char *pMem;
-
- f = gzopen(file, "wb");
- if (f == NULL) return -1;
-
- gzwrite(f, (void *)PcsxrHeader, 32);
- gzwrite(f, (void *)&SaveVersion, sizeof(u32));
- gzwrite(f, (void *)&Config.HLE, sizeof(boolean));
-
- pMem = (unsigned char *)malloc(128 * 96 * 3);
- if (pMem == NULL) return -1;
- GPU_getScreenPic(pMem);
- gzwrite(f, pMem, 128 * 96 * 3);
- free(pMem);
-
- if (Config.HLE)
- psxBiosFreeze(1);
-
- gzwrite(f, psxM, 0x00200000);
- gzwrite(f, psxR, 0x00080000);
- gzwrite(f, psxH, 0x00010000);
- gzwrite(f, (void *)&psxRegs, sizeof(psxRegs));
-
- // gpu
- gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
- gpufP->ulFreezeVersion = 1;
- GPU_freeze(1, gpufP);
- gzwrite(f, gpufP, sizeof(GPUFreeze_t));
- free(gpufP);
-
- // spu
- spufP = (SPUFreeze_t *) malloc(16);
- SPU_freeze(2, spufP);
- Size = spufP->Size; gzwrite(f, &Size, 4);
- free(spufP);
- spufP = (SPUFreeze_t *) malloc(Size);
- SPU_freeze(1, spufP);
- gzwrite(f, spufP, Size);
- free(spufP);
-
- sioFreeze(f, 1);
- cdrFreeze(f, 1);
- psxHwFreeze(f, 1);
- psxRcntFreeze(f, 1);
- mdecFreeze(f, 1);
-
- gzclose(f);
-
- return 0;
-}
-
-int LoadState(const char *file) {
- gzFile f;
- GPUFreeze_t *gpufP;
- SPUFreeze_t *spufP;
- int Size;
- char header[32];
- u32 version;
- boolean hle;
-
- f = gzopen(file, "rb");
- if (f == NULL) return -1;
-
- gzread(f, header, sizeof(header));
- gzread(f, &version, sizeof(u32));
- gzread(f, &hle, sizeof(boolean));
-
- if (strncmp("STv4 PCSXR", header, 10) != 0 || version != SaveVersion || hle != Config.HLE) {
- gzclose(f);
- return -1;
- }
-
- psxCpu->Reset();
- gzseek(f, 128 * 96 * 3, SEEK_CUR);
-
- gzread(f, psxM, 0x00200000);
- gzread(f, psxR, 0x00080000);
- gzread(f, psxH, 0x00010000);
- gzread(f, (void *)&psxRegs, sizeof(psxRegs));
-
- if (Config.HLE)
- psxBiosFreeze(0);
-
- // gpu
- gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
- gzread(f, gpufP, sizeof(GPUFreeze_t));
- GPU_freeze(0, gpufP);
- free(gpufP);
-
- // spu
- gzread(f, &Size, 4);
- spufP = (SPUFreeze_t *)malloc(Size);
- gzread(f, spufP, Size);
- SPU_freeze(0, spufP);
- free(spufP);
-
- sioFreeze(f, 0);
- cdrFreeze(f, 0);
- psxHwFreeze(f, 0);
- psxRcntFreeze(f, 0);
- mdecFreeze(f, 0);
-
- gzclose(f);
-
- return 0;
-}
-
-int CheckState(const char *file) {
- gzFile f;
- char header[32];
- u32 version;
- boolean hle;
-
- f = gzopen(file, "rb");
- if (f == NULL) return -1;
-
- gzread(f, header, sizeof(header));
- gzread(f, &version, sizeof(u32));
- gzread(f, &hle, sizeof(boolean));
-
- gzclose(f);
-
- if (strncmp("STv4 PCSXR", header, 10) != 0 || version != SaveVersion || hle != Config.HLE)
- return -1;
-
- return 0;
-}
-
-// NET Function Helpers
-
-int SendPcsxInfo() {
- if (NET_recvData == NULL || NET_sendData == NULL)
- return 0;
-
- NET_sendData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING);
- NET_sendData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING);
- NET_sendData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING);
- NET_sendData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING);
- NET_sendData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING);
- NET_sendData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
-
- return 0;
-}
-
-int RecvPcsxInfo() {
- int tmp;
-
- if (NET_recvData == NULL || NET_sendData == NULL)
- return 0;
-
- NET_recvData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING);
- NET_recvData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING);
- NET_recvData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING);
- NET_recvData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING);
- NET_recvData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING);
-
- SysUpdate();
-
- tmp = Config.Cpu;
- NET_recvData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
- if (tmp != Config.Cpu) {
- psxCpu->Shutdown();
-#ifdef PSXREC
- if (Config.Cpu == CPU_INTERPRETER) psxCpu = &psxInt;
- else psxCpu = &psxRec;
-#else
- psxCpu = &psxInt;
-#endif
- if (psxCpu->Init() == -1) {
- SysClose(); return -1;
- }
- psxCpu->Reset();
- }
-
- return 0;
-}
-
-// remove the leading and trailing spaces in a string
-void trim(char *str) {
- int pos = 0;
- char *dest = str;
-
- // skip leading blanks
- while (str[pos] <= ' ' && str[pos] > 0)
- pos++;
-
- while (str[pos]) {
- *(dest++) = str[pos];
- pos++;
- }
-
- *(dest--) = '\0'; // store the null
-
- // remove trailing blanks
- while (dest >= str && *dest <= ' ' && *dest > 0)
- *(dest--) = '\0';
-}
-
-// lookup table for crc calculation
-static unsigned short crctab[256] = {
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
- 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
- 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
- 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
- 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
- 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
- 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
- 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
- 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
- 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
- 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
- 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
- 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
- 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
- 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
- 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
- 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
- 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
- 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
- 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
- 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
- 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
- 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
- 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
- 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
- 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
- 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
-};
-
-u16 calcCrc(u8 *d, int len) {
- u16 crc = 0;
- int i;
-
- for (i = 0; i < len; i++) {
- crc = crctab[(crc >> 8) ^ d[i]] ^ (crc << 8);
- }
-
- return ~crc;
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* Miscellaneous functions, including savestates and CD-ROM loading. +*/ + +#include "misc.h" +#include "cdrom.h" +#include "mdec.h" +#include "ppf.h" + +char CdromId[10] = ""; +char CdromLabel[33] = ""; + +// PSX Executable types +#define PSX_EXE 1 +#define CPE_EXE 2 +#define COFF_EXE 3 +#define INVALID_EXE 4 + +#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]; +}; + +void mmssdd( char *b, char *p ) +{ + int m, s, d; +#if defined(__BIGENDIAN__) + int block = (b[0] & 0xff) | ((b[1] & 0xff) << 8) | ((b[2] & 0xff) << 16) | (b[3] << 24); +#else + int block = *((int*)b); +#endif + + block += 150; + m = block / 4500; // minutes + block = block - m * 4500; // minutes rest + s = block / 75; // seconds + d = block - s * 75; // seconds rest + + m = ((m / 10) << 4) | m % 10; + s = ((s / 10) << 4) | s % 10; + d = ((d / 10) << 4) | d % 10; + + p[0] = m; + p[1] = s; + p[2] = d; +} + +#define incTime() \ + time[0] = btoi(time[0]); time[1] = btoi(time[1]); time[2] = btoi(time[2]); \ + time[2]++; \ + if(time[2] == 75) { \ + time[2] = 0; \ + time[1]++; \ + if (time[1] == 60) { \ + time[1] = 0; \ + time[0]++; \ + } \ + } \ + time[0] = itob(time[0]); time[1] = itob(time[1]); time[2] = itob(time[2]); + +#define READTRACK() \ + if (CDR_readTrack(time) == -1) return -1; \ + buf = CDR_getBuffer(); \ + if (buf == NULL) return -1; else CheckPPFCache(buf, time[0], time[1], time[2]); + +#define READDIR(_dir) \ + READTRACK(); \ + memcpy(_dir, buf + 12, 2048); \ + \ + incTime(); \ + READTRACK(); \ + memcpy(_dir + 2048, buf + 12, 2048); + +int GetCdromFile(u8 *mdir, u8 *time, s8 *filename) { + struct iso_directory_record *dir; + char ddir[4096]; + u8 *buf; + int i; + + // only try to scan if a filename is given + if (!strlen(filename)) return -1; + + i = 0; + while (i < 4096) { + dir = (struct iso_directory_record*) &mdir[i]; + if (dir->length[0] == 0) { + return -1; + } + i += dir->length[0]; + + if (dir->flags[0] & 0x2) { // it's a dir + if (!strnicmp((char *)&dir->name[0], filename, dir->name_len[0])) { + if (filename[dir->name_len[0]] != '\\') continue; + + filename += dir->name_len[0] + 1; + + mmssdd(dir->extent, (char *)time); + READDIR(ddir); + i = 0; + mdir = ddir; + } + } else { + if (!strnicmp((char *)&dir->name[0], filename, strlen(filename))) { + mmssdd(dir->extent, (char *)time); + break; + } + } + } + return 0; +} + +int LoadCdrom() { + EXE_HEADER tmpHead; + struct iso_directory_record *dir; + u8 time[4], *buf; + u8 mdir[4096]; + s8 exename[256]; + + if (!Config.HLE) { + if (!Config.SlowBoot) psxRegs.pc = psxRegs.GPR.n.ra; + return 0; + } + + time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10); + + READTRACK(); + + // skip head and sub, and go to the root directory record + dir = (struct iso_directory_record*) &buf[12+156]; + + mmssdd(dir->extent, (char*)time); + + READDIR(mdir); + + // Load SYSTEM.CNF and scan for the main executable + if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") == -1) { + // if SYSTEM.CNF is missing, start an existing PSX.EXE + if (GetCdromFile(mdir, time, "PSX.EXE;1") == -1) return -1; + + READTRACK(); + } + else { + // read the SYSTEM.CNF + READTRACK(); + + sscanf((char *)buf + 12, "BOOT = cdrom:\\%256s", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + sscanf((char *)buf + 12, "BOOT = cdrom:%256s", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + char *ptr = strstr(buf + 12, "cdrom:"); + if (ptr != NULL) { + ptr += 6; + while (*ptr == '\\' || *ptr == '/') ptr++; + strncpy(exename, ptr, 255); + exename[255] = '\0'; + ptr = exename; + while (*ptr != '\0' && *ptr != '\r' && *ptr != '\n') ptr++; + *ptr = '\0'; + if (GetCdromFile(mdir, time, exename) == -1) + return -1; + } else + return -1; + } + } + + // Read the EXE-Header + READTRACK(); + } + + memcpy(&tmpHead, buf + 12, sizeof(EXE_HEADER)); + + psxRegs.pc = SWAP32(tmpHead.pc0); + psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0); + psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr); + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + + tmpHead.t_size = SWAP32(tmpHead.t_size); + tmpHead.t_addr = SWAP32(tmpHead.t_addr); + + // Read the rest of the main executable + while (tmpHead.t_size) { + void *ptr = (void *)PSXM(tmpHead.t_addr); + + incTime(); + READTRACK(); + + if (ptr != NULL) memcpy(ptr, buf+12, 2048); + + tmpHead.t_size -= 2048; + tmpHead.t_addr += 2048; + } + + return 0; +} + +int LoadCdromFile(const char *filename, EXE_HEADER *head) { + struct iso_directory_record *dir; + u8 time[4],*buf; + u8 mdir[4096], exename[256]; + u32 size, addr; + + sscanf(filename, "cdrom:\\%256s", exename); + + time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10); + + READTRACK(); + + // skip head and sub, and go to the root directory record + dir = (struct iso_directory_record *)&buf[12 + 156]; + + mmssdd(dir->extent, (char*)time); + + READDIR(mdir); + + if (GetCdromFile(mdir, time, exename) == -1) return -1; + + READTRACK(); + + memcpy(head, buf + 12, sizeof(EXE_HEADER)); + size = head->t_size; + addr = head->t_addr; + + while (size) { + incTime(); + READTRACK(); + + memcpy((void *)PSXM(addr), buf + 12, 2048); + + size -= 2048; + addr += 2048; + } + + return 0; +} + +int CheckCdrom() { + struct iso_directory_record *dir; + unsigned char time[4], *buf; + unsigned char mdir[4096]; + char exename[256]; + int i, c; + + FreePPFCache(); + + time[0] = itob(0); + time[1] = itob(2); + time[2] = itob(0x10); + + READTRACK(); + + CdromLabel[0] = '\0'; + CdromId[0] = '\0'; + + strncpy(CdromLabel, buf + 52, 32); + + // skip head and sub, and go to the root directory record + dir = (struct iso_directory_record *)&buf[12 + 156]; + + mmssdd(dir->extent, (char *)time); + + READDIR(mdir); + + if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") != -1) { + READTRACK(); + + sscanf((char *)buf + 12, "BOOT = cdrom:\\%256s", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + sscanf((char *)buf + 12, "BOOT = cdrom:%256s", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + char *ptr = strstr(buf + 12, "cdrom:"); // possibly the executable is in some subdir + if (ptr != NULL) { + ptr += 6; + while (*ptr == '\\' || *ptr == '/') ptr++; + strncpy(exename, ptr, 255); + exename[255] = '\0'; + ptr = exename; + while (*ptr != '\0' && *ptr != '\r' && *ptr != '\n') ptr++; + *ptr = '\0'; + if (GetCdromFile(mdir, time, exename) == -1) + return -1; // main executable not found + } else + return -1; + } + } + } else if (GetCdromFile(mdir, time, "PSX.EXE;1") != -1) { + strcpy(exename, "PSX.EXE;1"); + strcpy(CdromId, "SLUS99999"); + } else + return -1; // SYSTEM.CNF and PSX.EXE not found + + if (CdromId[0] == '\0') { + i = strlen(exename); + if (i >= 2) { + if (exename[i - 2] == ';') i-= 2; + c = 8; i--; + while (i >= 0 && c >= 0) { + if (isalnum(exename[i])) CdromId[c--] = exename[i]; + i--; + } + } + } + + if (Config.PsxAuto) { // autodetect system (pal or ntsc) + if((CdromId[2] == 'e') || (CdromId[2] == 'E') || + !strncmp(CdromId, "\0DTLS3035", 10) || + !strncmp(CdromId, "PBPX95001", 10) || // according to redump.org, these PAL + !strncmp(CdromId, "PBPX95007", 10) || // discs have a non-standard ID; + !strncmp(CdromId, "PBPX95008", 10)) // add more serials if they are discovered. + Config.PsxType = PSX_TYPE_PAL; // pal + else Config.PsxType = PSX_TYPE_NTSC; // ntsc + } + + if (CdromLabel[0] == ' ') { + strncpy(CdromLabel, CdromId, 9); + } + SysPrintf(_("CD-ROM Label: %.32s\n"), CdromLabel); + SysPrintf(_("CD-ROM ID: %.9s\n"), CdromId); + + BuildPPFCache(); + LoadSBI(); + + return 0; +} + +static int PSXGetFileType(FILE *f) { + unsigned long current; + u8 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 (SWAPu16(coff_hdr->f_magic) == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +static void LoadLibPS() { + char buf[MAXPATHLEN]; + FILE *f; + + // Load Net Yaroze runtime library (if exists) + sprintf(buf, "%s/libps.exe", Config.BiosDir); + f = fopen(buf, "rb"); + + if (f != NULL) { + fseek(f, 0x800, SEEK_SET); + fread(psxM + 0x10000, 0x61000, 1, f); + fclose(f); + } +} + +int Load(const char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + FILHDR coffHead; + AOUTHDR optHead; + SCNHDR section; + int type, i; + int retval = 0; + u8 opcode; + u32 section_address, section_size; + + strncpy(CdromId, "SLUS99999", 9); + strncpy(CdromLabel, "SLUS_999.99", 11); + + tmpFile = fopen(ExePath, "rb"); + if (tmpFile == NULL) { + SysPrintf(_("Error opening file: %s.\n"), ExePath); + retval = -1; + } else { + LoadLibPS(); + + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead, sizeof(EXE_HEADER), 1, tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread(PSXM(SWAP32(tmpHead.t_addr)), SWAP32(tmpHead.t_size), 1, tmpFile); + fclose(tmpFile); + psxRegs.pc = SWAP32(tmpHead.pc0); + psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0); + psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr); + if (psxRegs.GPR.n.sp == 0) + psxRegs.GPR.n.sp = 0x801fff00; + retval = 0; + break; + + case CPE_EXE: + fseek(tmpFile, 6, SEEK_SET); /* Something tells me we should go to 4 and read the "08 00" here... */ + do { + fread(&opcode, 1, 1, tmpFile); + switch (opcode) { + case 1: /* Section loading */ + fread(§ion_address, 4, 1, tmpFile); + fread(§ion_size, 4, 1, tmpFile); + section_address = SWAPu32(section_address); + section_size = SWAPu32(section_size); +#ifdef EMU_LOG + EMU_LOG("Loading %08X bytes from %08X to %08X\n", section_size, ftell(tmpFile), section_address); +#endif + fread(PSXM(section_address), section_size, 1, tmpFile); + break; + case 3: /* register loading (PC only?) */ + fseek(tmpFile, 2, SEEK_CUR); /* unknown field */ + fread(&psxRegs.pc, 4, 1, tmpFile); + psxRegs.pc = SWAPu32(psxRegs.pc); + break; + case 0: /* End of file */ + break; + default: + SysPrintf(_("Unknown CPE opcode %02x at position %08x.\n"), opcode, ftell(tmpFile) - 1); + retval = -1; + break; + } + } while (opcode != 0 && retval == 0); + break; + + case COFF_EXE: + fread(&coffHead, sizeof(coffHead), 1, tmpFile); + fread(&optHead, sizeof(optHead), 1, tmpFile); + + psxRegs.pc = SWAP32(optHead.entry); + psxRegs.GPR.n.sp = 0x801fff00; + + for (i = 0; i < SWAP16(coffHead.f_nscns); i++) { + fseek(tmpFile, sizeof(FILHDR) + SWAP16(coffHead.f_opthdr) + sizeof(section) * i, SEEK_SET); + fread(§ion, sizeof(section), 1, tmpFile); + + if (section.s_scnptr != 0) { + fseek(tmpFile, SWAP32(section.s_scnptr), SEEK_SET); + fread(PSXM(SWAP32(section.s_paddr)), SWAP32(section.s_size), 1, tmpFile); + } else { + memset(PSXM(SWAP32(section.s_paddr)), 0, SWAP32(section.s_size)); + } + } + break; + + case INVALID_EXE: + SysPrintf(_("This file does not appear to be a valid PSX file.\n")); + retval = -1; + break; + } + } + + if (retval != 0) { + CdromId[0] = '\0'; + CdromLabel[0] = '\0'; + } + + return retval; +} + +// STATES + +static const char PcsxrHeader[32] = "STv4 PCSXR v" PACKAGE_VERSION; + +// Savestate Versioning! +// If you make changes to the savestate version, please increment the value below. +static const u32 SaveVersion = 0x8b410007; + +int SaveState(const char *file) { + gzFile f; + GPUFreeze_t *gpufP; + SPUFreeze_t *spufP; + int Size; + unsigned char *pMem; + + f = gzopen(file, "wb"); + if (f == NULL) return -1; + + gzwrite(f, (void *)PcsxrHeader, 32); + gzwrite(f, (void *)&SaveVersion, sizeof(u32)); + gzwrite(f, (void *)&Config.HLE, sizeof(boolean)); + + pMem = (unsigned char *)malloc(128 * 96 * 3); + if (pMem == NULL) return -1; + GPU_getScreenPic(pMem); + gzwrite(f, pMem, 128 * 96 * 3); + free(pMem); + + if (Config.HLE) + psxBiosFreeze(1); + + gzwrite(f, psxM, 0x00200000); + gzwrite(f, psxR, 0x00080000); + gzwrite(f, psxH, 0x00010000); + gzwrite(f, (void *)&psxRegs, sizeof(psxRegs)); + + // gpu + gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t)); + gpufP->ulFreezeVersion = 1; + GPU_freeze(1, gpufP); + gzwrite(f, gpufP, sizeof(GPUFreeze_t)); + free(gpufP); + + // spu + spufP = (SPUFreeze_t *) malloc(16); + SPU_freeze(2, spufP); + Size = spufP->Size; gzwrite(f, &Size, 4); + free(spufP); + spufP = (SPUFreeze_t *) malloc(Size); + SPU_freeze(1, spufP); + gzwrite(f, spufP, Size); + free(spufP); + + sioFreeze(f, 1); + cdrFreeze(f, 1); + psxHwFreeze(f, 1); + psxRcntFreeze(f, 1); + mdecFreeze(f, 1); + + gzclose(f); + + return 0; +} + +int LoadState(const char *file) { + gzFile f; + GPUFreeze_t *gpufP; + SPUFreeze_t *spufP; + int Size; + char header[32]; + u32 version; + boolean hle; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, header, sizeof(header)); + gzread(f, &version, sizeof(u32)); + gzread(f, &hle, sizeof(boolean)); + + if (strncmp("STv4 PCSXR", header, 10) != 0 || version != SaveVersion || hle != Config.HLE) { + gzclose(f); + return -1; + } + + psxCpu->Reset(); + gzseek(f, 128 * 96 * 3, SEEK_CUR); + + gzread(f, psxM, 0x00200000); + gzread(f, psxR, 0x00080000); + gzread(f, psxH, 0x00010000); + gzread(f, (void *)&psxRegs, sizeof(psxRegs)); + + if (Config.HLE) + psxBiosFreeze(0); + + // gpu + gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t)); + gzread(f, gpufP, sizeof(GPUFreeze_t)); + GPU_freeze(0, gpufP); + free(gpufP); + + // spu + gzread(f, &Size, 4); + spufP = (SPUFreeze_t *)malloc(Size); + gzread(f, spufP, Size); + SPU_freeze(0, spufP); + free(spufP); + + sioFreeze(f, 0); + cdrFreeze(f, 0); + psxHwFreeze(f, 0); + psxRcntFreeze(f, 0); + mdecFreeze(f, 0); + + gzclose(f); + + return 0; +} + +int CheckState(const char *file) { + gzFile f; + char header[32]; + u32 version; + boolean hle; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, header, sizeof(header)); + gzread(f, &version, sizeof(u32)); + gzread(f, &hle, sizeof(boolean)); + + gzclose(f); + + if (strncmp("STv4 PCSXR", header, 10) != 0 || version != SaveVersion || hle != Config.HLE) + return -1; + + return 0; +} + +// NET Function Helpers + +int SendPcsxInfo() { + if (NET_recvData == NULL || NET_sendData == NULL) + return 0; + + NET_sendData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING); + NET_sendData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING); + NET_sendData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING); + NET_sendData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING); + NET_sendData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING); + NET_sendData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING); + + return 0; +} + +int RecvPcsxInfo() { + int tmp; + + if (NET_recvData == NULL || NET_sendData == NULL) + return 0; + + NET_recvData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING); + NET_recvData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING); + NET_recvData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING); + NET_recvData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING); + NET_recvData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING); + + SysUpdate(); + + tmp = Config.Cpu; + NET_recvData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING); + if (tmp != Config.Cpu) { + psxCpu->Shutdown(); +#ifdef PSXREC + if (Config.Cpu == CPU_INTERPRETER) psxCpu = &psxInt; + else psxCpu = &psxRec; +#else + psxCpu = &psxInt; +#endif + if (psxCpu->Init() == -1) { + SysClose(); return -1; + } + psxCpu->Reset(); + } + + return 0; +} + +// remove the leading and trailing spaces in a string +void trim(char *str) { + int pos = 0; + char *dest = str; + + // skip leading blanks + while (str[pos] <= ' ' && str[pos] > 0) + pos++; + + while (str[pos]) { + *(dest++) = str[pos]; + pos++; + } + + *(dest--) = '\0'; // store the null + + // remove trailing blanks + while (dest >= str && *dest <= ' ' && *dest > 0) + *(dest--) = '\0'; +} + +// lookup table for crc calculation +static unsigned short crctab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, + 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, + 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, + 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, + 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, + 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, + 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, + 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, + 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, + 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, + 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, + 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, + 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, + 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, + 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, + 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, + 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, + 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, + 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, + 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, + 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, + 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, + 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, + 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +u16 calcCrc(u8 *d, int len) { + u16 crc = 0; + int i; + + for (i = 0; i < len; i++) { + crc = crctab[(crc >> 8) ^ d[i]] ^ (crc << 8); + } + + return ~crc; +} diff --git a/libpcsxcore/plugins.c b/libpcsxcore/plugins.c index c8c01b8b..6ade3ce7 100644..100755 --- a/libpcsxcore/plugins.c +++ b/libpcsxcore/plugins.c @@ -1,839 +1,839 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* Plugin library callback/access functions.
-*/
-
-#include "plugins.h"
-#include "cdriso.h"
-
-static char IsoFile[MAXPATHLEN] = "";
-static s64 cdOpenCaseTime = 0;
-
-GPUupdateLace GPU_updateLace;
-GPUinit GPU_init;
-GPUshutdown GPU_shutdown;
-GPUconfigure GPU_configure;
-GPUtest GPU_test;
-GPUabout GPU_about;
-GPUopen GPU_open;
-GPUclose GPU_close;
-GPUreadStatus GPU_readStatus;
-GPUreadData GPU_readData;
-GPUreadDataMem GPU_readDataMem;
-GPUwriteStatus GPU_writeStatus;
-GPUwriteData GPU_writeData;
-GPUwriteDataMem GPU_writeDataMem;
-GPUdmaChain GPU_dmaChain;
-GPUkeypressed GPU_keypressed;
-GPUdisplayText GPU_displayText;
-GPUmakeSnapshot GPU_makeSnapshot;
-GPUfreeze GPU_freeze;
-GPUgetScreenPic GPU_getScreenPic;
-GPUshowScreenPic GPU_showScreenPic;
-GPUclearDynarec GPU_clearDynarec;
-GPUhSync GPU_hSync;
-GPUvBlank GPU_vBlank;
-GPUvisualVibration GPU_visualVibration;
-GPUcursor GPU_cursor;
-GPUaddVertex GPU_addVertex;
-
-CDRinit CDR_init;
-CDRshutdown CDR_shutdown;
-CDRopen CDR_open;
-CDRclose CDR_close;
-CDRtest CDR_test;
-CDRgetTN CDR_getTN;
-CDRgetTD CDR_getTD;
-CDRreadTrack CDR_readTrack;
-CDRgetBuffer CDR_getBuffer;
-CDRplay CDR_play;
-CDRstop CDR_stop;
-CDRgetStatus CDR_getStatus;
-CDRgetDriveLetter CDR_getDriveLetter;
-CDRgetBufferSub CDR_getBufferSub;
-CDRconfigure CDR_configure;
-CDRabout CDR_about;
-CDRsetfilename CDR_setfilename;
-CDRreadCDDA CDR_readCDDA;
-CDRgetTE CDR_getTE;
-
-SPUconfigure SPU_configure;
-SPUabout SPU_about;
-SPUinit SPU_init;
-SPUshutdown SPU_shutdown;
-SPUtest SPU_test;
-SPUopen SPU_open;
-SPUclose SPU_close;
-SPUplaySample SPU_playSample;
-SPUwriteRegister SPU_writeRegister;
-SPUreadRegister SPU_readRegister;
-SPUwriteDMA SPU_writeDMA;
-SPUreadDMA SPU_readDMA;
-SPUwriteDMAMem SPU_writeDMAMem;
-SPUreadDMAMem SPU_readDMAMem;
-SPUplayADPCMchannel SPU_playADPCMchannel;
-SPUfreeze SPU_freeze;
-SPUregisterCallback SPU_registerCallback;
-SPUasync SPU_async;
-SPUplayCDDAchannel SPU_playCDDAchannel;
-
-PADconfigure PAD1_configure;
-PADabout PAD1_about;
-PADinit PAD1_init;
-PADshutdown PAD1_shutdown;
-PADtest PAD1_test;
-PADopen PAD1_open;
-PADclose PAD1_close;
-PADquery PAD1_query;
-PADreadPort1 PAD1_readPort1;
-PADkeypressed PAD1_keypressed;
-PADstartPoll PAD1_startPoll;
-PADpoll PAD1_poll;
-PADsetSensitive PAD1_setSensitive;
-PADregisterVibration PAD1_registerVibration;
-PADregisterCursor PAD1_registerCursor;
-
-PADconfigure PAD2_configure;
-PADabout PAD2_about;
-PADinit PAD2_init;
-PADshutdown PAD2_shutdown;
-PADtest PAD2_test;
-PADopen PAD2_open;
-PADclose PAD2_close;
-PADquery PAD2_query;
-PADreadPort2 PAD2_readPort2;
-PADkeypressed PAD2_keypressed;
-PADstartPoll PAD2_startPoll;
-PADpoll PAD2_poll;
-PADsetSensitive PAD2_setSensitive;
-PADregisterVibration PAD2_registerVibration;
-PADregisterCursor PAD2_registerCursor;
-
-NETinit NET_init;
-NETshutdown NET_shutdown;
-NETopen NET_open;
-NETclose NET_close;
-NETtest NET_test;
-NETconfigure NET_configure;
-NETabout NET_about;
-NETpause NET_pause;
-NETresume NET_resume;
-NETqueryPlayer NET_queryPlayer;
-NETsendData NET_sendData;
-NETrecvData NET_recvData;
-NETsendPadData NET_sendPadData;
-NETrecvPadData NET_recvPadData;
-NETsetInfo NET_setInfo;
-NETkeypressed NET_keypressed;
-
-#ifdef ENABLE_SIO1API
-
-SIO1init SIO1_init;
-SIO1shutdown SIO1_shutdown;
-SIO1open SIO1_open;
-SIO1close SIO1_close;
-SIO1test SIO1_test;
-SIO1configure SIO1_configure;
-SIO1about SIO1_about;
-SIO1pause SIO1_pause;
-SIO1resume SIO1_resume;
-SIO1keypressed SIO1_keypressed;
-SIO1writeData8 SIO1_writeData8;
-SIO1writeData16 SIO1_writeData16;
-SIO1writeData32 SIO1_writeData32;
-SIO1writeStat16 SIO1_writeStat16;
-SIO1writeStat32 SIO1_writeStat32;
-SIO1writeMode16 SIO1_writeMode16;
-SIO1writeMode32 SIO1_writeMode32;
-SIO1writeCtrl16 SIO1_writeCtrl16;
-SIO1writeCtrl32 SIO1_writeCtrl32;
-SIO1writeBaud16 SIO1_writeBaud16;
-SIO1writeBaud32 SIO1_writeBaud32;
-SIO1readData8 SIO1_readData8;
-SIO1readData16 SIO1_readData16;
-SIO1readData32 SIO1_readData32;
-SIO1readStat16 SIO1_readStat16;
-SIO1readStat32 SIO1_readStat32;
-SIO1readMode16 SIO1_readMode16;
-SIO1readMode32 SIO1_readMode32;
-SIO1readCtrl16 SIO1_readCtrl16;
-SIO1readCtrl32 SIO1_readCtrl32;
-SIO1readBaud16 SIO1_readBaud16;
-SIO1readBaud32 SIO1_readBaud32;
-SIO1registerCallback SIO1_registerCallback;
-
-#endif
-
-static const char *err;
-
-#define CheckErr(func) { \
- err = SysLibError(); \
- if (err != NULL) { SysMessage(_("Error loading %s: %s"), func, err); return -1; } \
-}
-
-#define LoadSym(dest, src, name, checkerr) { \
- dest = (src)SysLoadSym(drv, name); \
- if (checkerr) { CheckErr(name); } else SysLibError(); \
-}
-
-void *hGPUDriver = NULL;
-
-void CALLBACK GPU__displayText(char *pText) {
- SysPrintf("%s\n", pText);
-}
-
-long CALLBACK GPU__configure(void) { return 0; }
-long CALLBACK GPU__test(void) { return 0; }
-void CALLBACK GPU__about(void) {}
-void CALLBACK GPU__makeSnapshot(void) {}
-void CALLBACK GPU__keypressed(int key) {}
-long CALLBACK GPU__getScreenPic(unsigned char *pMem) { return -1; }
-long CALLBACK GPU__showScreenPic(unsigned char *pMem) { return -1; }
-void CALLBACK GPU__clearDynarec(void (CALLBACK *callback)(void)) {}
-void CALLBACK GPU__hSync(int val) {}
-void CALLBACK GPU__vBlank(int val) {}
-void CALLBACK GPU__visualVibration(unsigned long iSmall, unsigned long iBig) {}
-void CALLBACK GPU__cursor(int player, int x, int y) {}
-void CALLBACK GPU__addVertex(short sx,short sy,s64 fx,s64 fy,s64 fz) {}
-
-#define LoadGpuSym1(dest, name) \
- LoadSym(GPU_##dest, GPU##dest, name, TRUE);
-
-#define LoadGpuSym0(dest, name) \
- LoadSym(GPU_##dest, GPU##dest, name, FALSE); \
- if (GPU_##dest == NULL) GPU_##dest = (GPU##dest) GPU__##dest;
-
-#define LoadGpuSymN(dest, name) \
- LoadSym(GPU_##dest, GPU##dest, name, FALSE);
-
-static int LoadGPUplugin(const char *GPUdll) {
- void *drv;
-
- hGPUDriver = SysLoadLibrary(GPUdll);
- if (hGPUDriver == NULL) {
- GPU_configure = NULL;
- SysMessage (_("Could not load GPU plugin %s!"), GPUdll); return -1;
- }
- drv = hGPUDriver;
- LoadGpuSym1(init, "GPUinit");
- LoadGpuSym1(shutdown, "GPUshutdown");
- LoadGpuSym1(open, "GPUopen");
- LoadGpuSym1(close, "GPUclose");
- LoadGpuSym1(readData, "GPUreadData");
- LoadGpuSym1(readDataMem, "GPUreadDataMem");
- LoadGpuSym1(readStatus, "GPUreadStatus");
- LoadGpuSym1(writeData, "GPUwriteData");
- LoadGpuSym1(writeDataMem, "GPUwriteDataMem");
- LoadGpuSym1(writeStatus, "GPUwriteStatus");
- LoadGpuSym1(dmaChain, "GPUdmaChain");
- LoadGpuSym1(updateLace, "GPUupdateLace");
- LoadGpuSym0(keypressed, "GPUkeypressed");
- LoadGpuSym0(displayText, "GPUdisplayText");
- LoadGpuSym0(makeSnapshot, "GPUmakeSnapshot");
- LoadGpuSym1(freeze, "GPUfreeze");
- LoadGpuSym0(getScreenPic, "GPUgetScreenPic");
- LoadGpuSym0(showScreenPic, "GPUshowScreenPic");
- LoadGpuSym0(clearDynarec, "GPUclearDynarec");
- LoadGpuSym0(hSync, "GPUhSync");
- LoadGpuSym0(vBlank, "GPUvBlank");
- LoadGpuSym0(visualVibration, "GPUvisualVibration");
- LoadGpuSym0(cursor, "GPUcursor");
- LoadGpuSym0(addVertex, "GPUaddVertex");
- LoadGpuSym0(configure, "GPUconfigure");
- LoadGpuSym0(test, "GPUtest");
- LoadGpuSym0(about, "GPUabout");
-
- return 0;
-}
-
-void *hCDRDriver = NULL;
-
-long CALLBACK CDR__play(unsigned char *sector) { return 0; }
-long CALLBACK CDR__stop(void) { return 0; }
-
-long CALLBACK CDR__getStatus(struct CdrStat *stat) {
- if (cdOpenCaseTime < 0 || cdOpenCaseTime > (s64)time(NULL))
- stat->Status = 0x10;
- else
- stat->Status = 0;
-
- return 0;
-}
-
-char* CALLBACK CDR__getDriveLetter(void) { return NULL; }
-long CALLBACK CDR__configure(void) { return 0; }
-long CALLBACK CDR__test(void) { return 0; }
-void CALLBACK CDR__about(void) {}
-long CALLBACK CDR__setfilename(char*filename) { return 0; }
-
-#define LoadCdrSym1(dest, name) \
- LoadSym(CDR_##dest, CDR##dest, name, TRUE);
-
-#define LoadCdrSym0(dest, name) \
- LoadSym(CDR_##dest, CDR##dest, name, FALSE); \
- if (CDR_##dest == NULL) CDR_##dest = (CDR##dest) CDR__##dest;
-
-#define LoadCdrSymN(dest, name) \
- LoadSym(CDR_##dest, CDR##dest, name, FALSE);
-
-static int LoadCDRplugin(const char *CDRdll) {
- void *drv;
-
- if (CDRdll == NULL) {
- cdrIsoInit();
- return 0;
- }
-
- hCDRDriver = SysLoadLibrary(CDRdll);
- if (hCDRDriver == NULL) {
- CDR_configure = NULL;
- SysMessage (_("Could not load CD-ROM plugin %s!"), CDRdll); return -1;
- }
- drv = hCDRDriver;
- LoadCdrSym1(init, "CDRinit");
- LoadCdrSym1(shutdown, "CDRshutdown");
- LoadCdrSym1(open, "CDRopen");
- LoadCdrSym1(close, "CDRclose");
- LoadCdrSym1(getTN, "CDRgetTN");
- LoadCdrSym1(getTD, "CDRgetTD");
- LoadCdrSym1(readTrack, "CDRreadTrack");
- LoadCdrSym1(getBuffer, "CDRgetBuffer");
- LoadCdrSym1(getBufferSub, "CDRgetBufferSub");
- LoadCdrSym0(play, "CDRplay");
- LoadCdrSym0(stop, "CDRstop");
- LoadCdrSym0(getStatus, "CDRgetStatus");
- LoadCdrSym0(getDriveLetter, "CDRgetDriveLetter");
- LoadCdrSym0(configure, "CDRconfigure");
- LoadCdrSym0(test, "CDRtest");
- LoadCdrSym0(about, "CDRabout");
- LoadCdrSym0(setfilename, "CDRsetfilename");
- LoadCdrSymN(readCDDA, "CDRreadCDDA");
- LoadCdrSymN(getTE, "CDRgetTE");
-
- return 0;
-}
-
-void *hSPUDriver = NULL;
-
-long CALLBACK SPU__configure(void) { return 0; }
-void CALLBACK SPU__about(void) {}
-long CALLBACK SPU__test(void) { return 0; }
-
-#define LoadSpuSym1(dest, name) \
- LoadSym(SPU_##dest, SPU##dest, name, TRUE);
-
-#define LoadSpuSym0(dest, name) \
- LoadSym(SPU_##dest, SPU##dest, name, FALSE); \
- if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest;
-
-#define LoadSpuSymN(dest, name) \
- LoadSym(SPU_##dest, SPU##dest, name, FALSE);
-
-static int LoadSPUplugin(const char *SPUdll) {
- void *drv;
-
- hSPUDriver = SysLoadLibrary(SPUdll);
- if (hSPUDriver == NULL) {
- SPU_configure = NULL;
- SysMessage (_("Could not load SPU plugin %s!"), SPUdll); return -1;
- }
- drv = hSPUDriver;
- LoadSpuSym1(init, "SPUinit");
- LoadSpuSym1(shutdown, "SPUshutdown");
- LoadSpuSym1(open, "SPUopen");
- LoadSpuSym1(close, "SPUclose");
- LoadSpuSym0(configure, "SPUconfigure");
- LoadSpuSym0(about, "SPUabout");
- LoadSpuSym0(test, "SPUtest");
- LoadSpuSym1(writeRegister, "SPUwriteRegister");
- LoadSpuSym1(readRegister, "SPUreadRegister");
- LoadSpuSym1(writeDMA, "SPUwriteDMA");
- LoadSpuSym1(readDMA, "SPUreadDMA");
- LoadSpuSym1(writeDMAMem, "SPUwriteDMAMem");
- LoadSpuSym1(readDMAMem, "SPUreadDMAMem");
- LoadSpuSym1(playADPCMchannel, "SPUplayADPCMchannel");
- LoadSpuSym1(freeze, "SPUfreeze");
- LoadSpuSym1(registerCallback, "SPUregisterCallback");
- LoadSpuSymN(async, "SPUasync");
- LoadSpuSymN(playCDDAchannel, "SPUplayCDDAchannel");
-
- return 0;
-}
-
-void *hPAD1Driver = NULL;
-void *hPAD2Driver = NULL;
-
-static unsigned char buf[256];
-unsigned char stdpar[10] = { 0x00, 0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-unsigned char mousepar[8] = { 0x00, 0x12, 0x5a, 0xff, 0xff, 0xff, 0xff };
-unsigned char analogpar[9] = { 0x00, 0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-static int bufcount, bufc;
-
-PadDataS padd1, padd2;
-
-unsigned char _PADstartPoll(PadDataS *pad) {
- bufc = 0;
-
- switch (pad->controllerType) {
- case PSE_PAD_TYPE_MOUSE:
- mousepar[3] = pad->buttonStatus & 0xff;
- mousepar[4] = pad->buttonStatus >> 8;
- mousepar[5] = pad->moveX;
- mousepar[6] = pad->moveY;
-
- memcpy(buf, mousepar, 7);
- bufcount = 6;
- break;
- case PSE_PAD_TYPE_NEGCON: // npc101/npc104(slph00001/slph00069)
- analogpar[1] = 0x23;
- analogpar[3] = pad->buttonStatus & 0xff;
- analogpar[4] = pad->buttonStatus >> 8;
- analogpar[5] = pad->rightJoyX;
- analogpar[6] = pad->rightJoyY;
- analogpar[7] = pad->leftJoyX;
- analogpar[8] = pad->leftJoyY;
-
- memcpy(buf, analogpar, 9);
- bufcount = 8;
- break;
- case PSE_PAD_TYPE_ANALOGPAD: // scph1150
- analogpar[1] = 0x73;
- analogpar[3] = pad->buttonStatus & 0xff;
- analogpar[4] = pad->buttonStatus >> 8;
- analogpar[5] = pad->rightJoyX;
- analogpar[6] = pad->rightJoyY;
- analogpar[7] = pad->leftJoyX;
- analogpar[8] = pad->leftJoyY;
-
- memcpy(buf, analogpar, 9);
- bufcount = 8;
- break;
- case PSE_PAD_TYPE_ANALOGJOY: // scph1110
- analogpar[1] = 0x53;
- analogpar[3] = pad->buttonStatus & 0xff;
- analogpar[4] = pad->buttonStatus >> 8;
- analogpar[5] = pad->rightJoyX;
- analogpar[6] = pad->rightJoyY;
- analogpar[7] = pad->leftJoyX;
- analogpar[8] = pad->leftJoyY;
-
- memcpy(buf, analogpar, 9);
- bufcount = 8;
- break;
- case PSE_PAD_TYPE_STANDARD:
- default:
- stdpar[3] = pad->buttonStatus & 0xff;
- stdpar[4] = pad->buttonStatus >> 8;
-
- memcpy(buf, stdpar, 5);
- bufcount = 4;
- }
-
- return buf[bufc++];
-}
-
-unsigned char _PADpoll(unsigned char value) {
- if (bufc > bufcount) return 0;
- return buf[bufc++];
-}
-
-unsigned char CALLBACK PAD1__startPoll(int pad) {
- PadDataS padd;
-
- PAD1_readPort1(&padd);
-
- return _PADstartPoll(&padd);
-}
-
-unsigned char CALLBACK PAD1__poll(unsigned char value) {
- return _PADpoll(value);
-}
-
-long CALLBACK PAD1__configure(void) { return 0; }
-void CALLBACK PAD1__about(void) {}
-long CALLBACK PAD1__test(void) { return 0; }
-long CALLBACK PAD1__query(void) { return 3; }
-long CALLBACK PAD1__keypressed() { return 0; }
-void CALLBACK PAD1__registerVibration(void (CALLBACK *callback)(unsigned long, unsigned long)) {}
-void CALLBACK PAD1__registerCursor(void (CALLBACK *callback)(int, int, int)) {}
-
-#define LoadPad1Sym1(dest, name) \
- LoadSym(PAD1_##dest, PAD##dest, name, TRUE);
-
-#define LoadPad1SymN(dest, name) \
- LoadSym(PAD1_##dest, PAD##dest, name, FALSE);
-
-#define LoadPad1Sym0(dest, name) \
- LoadSym(PAD1_##dest, PAD##dest, name, FALSE); \
- if (PAD1_##dest == NULL) PAD1_##dest = (PAD##dest) PAD1__##dest;
-
-static int LoadPAD1plugin(const char *PAD1dll) {
- void *drv;
-
- hPAD1Driver = SysLoadLibrary(PAD1dll);
- if (hPAD1Driver == NULL) {
- PAD1_configure = NULL;
- SysMessage (_("Could not load Controller 1 plugin %s!"), PAD1dll); return -1;
- }
- drv = hPAD1Driver;
- LoadPad1Sym1(init, "PADinit");
- LoadPad1Sym1(shutdown, "PADshutdown");
- LoadPad1Sym1(open, "PADopen");
- LoadPad1Sym1(close, "PADclose");
- LoadPad1Sym0(query, "PADquery");
- LoadPad1Sym1(readPort1, "PADreadPort1");
- LoadPad1Sym0(configure, "PADconfigure");
- LoadPad1Sym0(test, "PADtest");
- LoadPad1Sym0(about, "PADabout");
- LoadPad1Sym0(keypressed, "PADkeypressed");
- LoadPad1Sym0(startPoll, "PADstartPoll");
- LoadPad1Sym0(poll, "PADpoll");
- LoadPad1SymN(setSensitive, "PADsetSensitive");
- LoadPad1Sym0(registerVibration, "PADregisterVibration");
- LoadPad1Sym0(registerCursor, "PADregisterCursor");
-
- return 0;
-}
-
-unsigned char CALLBACK PAD2__startPoll(int pad) {
- PadDataS padd;
-
- PAD2_readPort2(&padd);
-
- return _PADstartPoll(&padd);
-}
-
-unsigned char CALLBACK PAD2__poll(unsigned char value) {
- return _PADpoll(value);
-}
-
-long CALLBACK PAD2__configure(void) { return 0; }
-void CALLBACK PAD2__about(void) {}
-long CALLBACK PAD2__test(void) { return 0; }
-long CALLBACK PAD2__query(void) { return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; }
-long CALLBACK PAD2__keypressed() { return 0; }
-void CALLBACK PAD2__registerVibration(void (CALLBACK *callback)(unsigned long, unsigned long)) {}
-void CALLBACK PAD2__registerCursor(void (CALLBACK *callback)(int, int, int)) {}
-
-#define LoadPad2Sym1(dest, name) \
- LoadSym(PAD2_##dest, PAD##dest, name, TRUE);
-
-#define LoadPad2Sym0(dest, name) \
- LoadSym(PAD2_##dest, PAD##dest, name, FALSE); \
- if (PAD2_##dest == NULL) PAD2_##dest = (PAD##dest) PAD2__##dest;
-
-#define LoadPad2SymN(dest, name) \
- LoadSym(PAD2_##dest, PAD##dest, name, FALSE);
-
-static int LoadPAD2plugin(const char *PAD2dll) {
- void *drv;
-
- hPAD2Driver = SysLoadLibrary(PAD2dll);
- if (hPAD2Driver == NULL) {
- PAD2_configure = NULL;
- SysMessage (_("Could not load Controller 2 plugin %s!"), PAD2dll); return -1;
- }
- drv = hPAD2Driver;
- LoadPad2Sym1(init, "PADinit");
- LoadPad2Sym1(shutdown, "PADshutdown");
- LoadPad2Sym1(open, "PADopen");
- LoadPad2Sym1(close, "PADclose");
- LoadPad2Sym0(query, "PADquery");
- LoadPad2Sym1(readPort2, "PADreadPort2");
- LoadPad2Sym0(configure, "PADconfigure");
- LoadPad2Sym0(test, "PADtest");
- LoadPad2Sym0(about, "PADabout");
- LoadPad2Sym0(keypressed, "PADkeypressed");
- LoadPad2Sym0(startPoll, "PADstartPoll");
- LoadPad2Sym0(poll, "PADpoll");
- LoadPad2SymN(setSensitive, "PADsetSensitive");
- LoadPad2Sym0(registerVibration, "PADregisterVibration");
- LoadPad2Sym0(registerCursor, "PADregisterCursor");
-
- return 0;
-}
-
-void *hNETDriver = NULL;
-
-void CALLBACK NET__setInfo(netInfo *info) {}
-void CALLBACK NET__keypressed(int key) {}
-long CALLBACK NET__configure(void) { return 0; }
-long CALLBACK NET__test(void) { return 0; }
-void CALLBACK NET__about(void) {}
-
-#define LoadNetSym1(dest, name) \
- LoadSym(NET_##dest, NET##dest, name, TRUE);
-
-#define LoadNetSymN(dest, name) \
- LoadSym(NET_##dest, NET##dest, name, FALSE);
-
-#define LoadNetSym0(dest, name) \
- LoadSym(NET_##dest, NET##dest, name, FALSE); \
- if (NET_##dest == NULL) NET_##dest = (NET##dest) NET__##dest;
-
-static int LoadNETplugin(const char *NETdll) {
- void *drv;
-
- hNETDriver = SysLoadLibrary(NETdll);
- if (hNETDriver == NULL) {
- SysMessage (_("Could not load NetPlay plugin %s!"), NETdll); return -1;
- }
- drv = hNETDriver;
- LoadNetSym1(init, "NETinit");
- LoadNetSym1(shutdown, "NETshutdown");
- LoadNetSym1(open, "NETopen");
- LoadNetSym1(close, "NETclose");
- LoadNetSymN(sendData, "NETsendData");
- LoadNetSymN(recvData, "NETrecvData");
- LoadNetSym1(sendPadData, "NETsendPadData");
- LoadNetSym1(recvPadData, "NETrecvPadData");
- LoadNetSym1(queryPlayer, "NETqueryPlayer");
- LoadNetSym1(pause, "NETpause");
- LoadNetSym1(resume, "NETresume");
- LoadNetSym0(setInfo, "NETsetInfo");
- LoadNetSym0(keypressed, "NETkeypressed");
- LoadNetSym0(configure, "NETconfigure");
- LoadNetSym0(test, "NETtest");
- LoadNetSym0(about, "NETabout");
-
- return 0;
-}
-
-#ifdef ENABLE_SIO1API
-
-void *hSIO1Driver = NULL;
-
-long CALLBACK SIO1__init(void) { return 0; }
-long CALLBACK SIO1__shutdown(void) { return 0; }
-long CALLBACK SIO1__open(void) { return 0; }
-long CALLBACK SIO1__close(void) { return 0; }
-long CALLBACK SIO1__configure(void) { return 0; }
-long CALLBACK SIO1__test(void) { return 0; }
-void CALLBACK SIO1__about(void) {}
-void CALLBACK SIO1__pause(void) {}
-void CALLBACK SIO1__resume(void) {}
-long CALLBACK SIO1__keypressed(int key) { return 0; }
-void CALLBACK SIO1__writeData8(unsigned char val) {}
-void CALLBACK SIO1__writeData16(unsigned short val) {}
-void CALLBACK SIO1__writeData32(unsigned long val) {}
-void CALLBACK SIO1__writeStat16(unsigned short val) {}
-void CALLBACK SIO1__writeStat32(unsigned long val) {}
-void CALLBACK SIO1__writeMode16(unsigned short val) {}
-void CALLBACK SIO1__writeMode32(unsigned long val) {}
-void CALLBACK SIO1__writeCtrl16(unsigned short val) {}
-void CALLBACK SIO1__writeCtrl32(unsigned long val) {}
-void CALLBACK SIO1__writeBaud16(unsigned short val) {}
-void CALLBACK SIO1__writeBaud32(unsigned long val) {}
-unsigned char CALLBACK SIO1__readData8(void) { return 0; }
-unsigned short CALLBACK SIO1__readData16(void) { return 0; }
-unsigned long CALLBACK SIO1__readData32(void) { return 0; }
-unsigned short CALLBACK SIO1__readStat16(void) { return 0; }
-unsigned long CALLBACK SIO1__readStat32(void) { return 0; }
-unsigned short CALLBACK SIO1__readMode16(void) { return 0; }
-unsigned long CALLBACK SIO1__readMode32(void) { return 0; }
-unsigned short CALLBACK SIO1__readCtrl16(void) { return 0; }
-unsigned long CALLBACK SIO1__readCtrl32(void) { return 0; }
-unsigned short CALLBACK SIO1__readBaud16(void) { return 0; }
-unsigned long CALLBACK SIO1__readBaud32(void) { return 0; }
-void CALLBACK SIO1__registerCallback(void (CALLBACK *callback)(void)) {};
-
-void CALLBACK SIO1irq(void) {
- psxHu32ref(0x1070) |= SWAPu32(0x100);
-}
-
-#define LoadSio1Sym1(dest, name) \
- LoadSym(SIO1_##dest, SIO1##dest, name, TRUE);
-
-#define LoadSio1SymN(dest, name) \
- LoadSym(SIO1_##dest, SIO1##dest, name, FALSE);
-
-#define LoadSio1Sym0(dest, name) \
- LoadSym(SIO1_##dest, SIO1##dest, name, FALSE); \
- if (SIO1_##dest == NULL) SIO1_##dest = (SIO1##dest) SIO1__##dest;
-
-static int LoadSIO1plugin(const char *SIO1dll) {
- void *drv;
-
- hSIO1Driver = SysLoadLibrary(SIO1dll);
- if (hSIO1Driver == NULL) {
- SysMessage (_("Could not load SIO1 plugin %s!"), SIO1dll); return -1;
- }
- drv = hSIO1Driver;
-
- LoadSio1Sym0(init, "SIO1init");
- LoadSio1Sym0(shutdown, "SIO1shutdown");
- LoadSio1Sym0(open, "SIO1open");
- LoadSio1Sym0(close, "SIO1close");
- LoadSio1Sym0(pause, "SIO1pause");
- LoadSio1Sym0(resume, "SIO1resume");
- LoadSio1Sym0(keypressed, "SIO1keypressed");
- LoadSio1Sym0(configure, "SIO1configure");
- LoadSio1Sym0(test, "SIO1test");
- LoadSio1Sym0(about, "SIO1about");
- LoadSio1Sym0(writeData8, "SIO1writeData8");
- LoadSio1Sym0(writeData16, "SIO1writeData16");
- LoadSio1Sym0(writeData32, "SIO1writeData32");
- LoadSio1Sym0(writeStat16, "SIO1writeStat16");
- LoadSio1Sym0(writeStat32, "SIO1writeStat32");
- LoadSio1Sym0(writeMode16, "SIO1writeMode16");
- LoadSio1Sym0(writeMode32, "SIO1writeMode32");
- LoadSio1Sym0(writeCtrl16, "SIO1writeCtrl16");
- LoadSio1Sym0(writeCtrl32, "SIO1writeCtrl32");
- LoadSio1Sym0(writeBaud16, "SIO1writeBaud16");
- LoadSio1Sym0(writeBaud32, "SIO1writeBaud32");
- LoadSio1Sym0(readData16, "SIO1readData16");
- LoadSio1Sym0(readData32, "SIO1readData32");
- LoadSio1Sym0(readStat16, "SIO1readStat16");
- LoadSio1Sym0(readStat32, "SIO1readStat32");
- LoadSio1Sym0(readMode16, "SIO1readMode16");
- LoadSio1Sym0(readMode32, "SIO1readMode32");
- LoadSio1Sym0(readCtrl16, "SIO1readCtrl16");
- LoadSio1Sym0(readCtrl32, "SIO1readCtrl32");
- LoadSio1Sym0(readBaud16, "SIO1readBaud16");
- LoadSio1Sym0(readBaud32, "SIO1readBaud32");
- LoadSio1Sym0(registerCallback, "SIO1registerCallback");
-
- return 0;
-}
-
-#endif
-
-void CALLBACK clearDynarec(void) {
- psxCpu->Reset();
-}
-
-int LoadPlugins() {
- int ret;
- char Plugin[MAXPATHLEN];
-
- ReleasePlugins();
-
- if (UsingIso()) {
- LoadCDRplugin(NULL);
- } else {
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
- if (LoadCDRplugin(Plugin) == -1) return -1;
- }
-
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Gpu);
- if (LoadGPUplugin(Plugin) == -1) return -1;
-
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Spu);
- if (LoadSPUplugin(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;
-
- if (strcmp("Disabled", Config.Net) == 0 || strcmp("", Config.Net) == 0)
- Config.UseNet = FALSE;
- else {
- Config.UseNet = TRUE;
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Net);
- if (LoadNETplugin(Plugin) == -1) Config.UseNet = FALSE;
- }
-
-#ifdef ENABLE_SIO1API
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Sio1);
- if (LoadSIO1plugin(Plugin) == -1) return -1;
-#endif
-
- ret = CDR_init();
- if (ret < 0) { SysMessage (_("Error initializing CD-ROM plugin: %d"), ret); return -1; }
- ret = GPU_init();
- if (ret < 0) { SysMessage (_("Error initializing GPU plugin: %d"), ret); return -1; }
- ret = SPU_init();
- if (ret < 0) { SysMessage (_("Error initializing SPU plugin: %d"), ret); return -1; }
- ret = PAD1_init(1);
- if (ret < 0) { SysMessage (_("Error initializing Controller 1 plugin: %d"), ret); return -1; }
- ret = PAD2_init(2);
- if (ret < 0) { SysMessage (_("Error initializing Controller 2 plugin: %d"), ret); return -1; }
-
- if (Config.UseNet) {
- ret = NET_init();
- if (ret < 0) { SysMessage (_("Error initializing NetPlay plugin: %d"), ret); return -1; }
- }
-
-#ifdef ENABLE_SIO1API
- ret = SIO1_init();
- if (ret < 0) { SysMessage (_("Error initializing SIO1 plugin: %d"), ret); return -1; }
-#endif
-
- SysPrintf(_("Plugins loaded.\n"));
- return 0;
-}
-
-void ReleasePlugins() {
- if (Config.UseNet) {
- int ret = NET_close();
- if (ret < 0) Config.UseNet = FALSE;
- }
- NetOpened = FALSE;
-
- if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
- if (hGPUDriver != NULL) GPU_shutdown();
- if (hSPUDriver != NULL) SPU_shutdown();
- if (hPAD1Driver != NULL) PAD1_shutdown();
- if (hPAD2Driver != NULL) PAD2_shutdown();
-
- if (Config.UseNet && hNETDriver != NULL) NET_shutdown();
-
- if (hCDRDriver != NULL) SysCloseLibrary(hCDRDriver); hCDRDriver = NULL;
- if (hGPUDriver != NULL) SysCloseLibrary(hGPUDriver); hGPUDriver = NULL;
- if (hSPUDriver != NULL) SysCloseLibrary(hSPUDriver); hSPUDriver = NULL;
- if (hPAD1Driver != NULL) SysCloseLibrary(hPAD1Driver); hPAD1Driver = NULL;
- if (hPAD2Driver != NULL) SysCloseLibrary(hPAD2Driver); hPAD2Driver = NULL;
-
- if (Config.UseNet && hNETDriver != NULL) {
- SysCloseLibrary(hNETDriver); hNETDriver = NULL;
- }
-
-#ifdef ENABLE_SIO1API
- if (hSIO1Driver != NULL) {
- SIO1_shutdown();
- SysCloseLibrary(hSIO1Driver);
- hSIO1Driver = NULL;
- }
-#endif
-}
-
-void SetIsoFile(const char *filename) {
- if (filename == NULL) {
- IsoFile[0] = '\0';
- return;
- }
- strncpy(IsoFile, filename, MAXPATHLEN);
-}
-
-const char *GetIsoFile(void) {
- return IsoFile;
-}
-
-boolean UsingIso(void) {
- return (IsoFile[0] != '\0');
-}
-
-void SetCdOpenCaseTime(s64 time) {
- cdOpenCaseTime = time;
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* Plugin library callback/access functions. +*/ + +#include "plugins.h" +#include "cdriso.h" + +static char IsoFile[MAXPATHLEN] = ""; +static s64 cdOpenCaseTime = 0; + +GPUupdateLace GPU_updateLace; +GPUinit GPU_init; +GPUshutdown GPU_shutdown; +GPUconfigure GPU_configure; +GPUtest GPU_test; +GPUabout GPU_about; +GPUopen GPU_open; +GPUclose GPU_close; +GPUreadStatus GPU_readStatus; +GPUreadData GPU_readData; +GPUreadDataMem GPU_readDataMem; +GPUwriteStatus GPU_writeStatus; +GPUwriteData GPU_writeData; +GPUwriteDataMem GPU_writeDataMem; +GPUdmaChain GPU_dmaChain; +GPUkeypressed GPU_keypressed; +GPUdisplayText GPU_displayText; +GPUmakeSnapshot GPU_makeSnapshot; +GPUfreeze GPU_freeze; +GPUgetScreenPic GPU_getScreenPic; +GPUshowScreenPic GPU_showScreenPic; +GPUclearDynarec GPU_clearDynarec; +GPUhSync GPU_hSync; +GPUvBlank GPU_vBlank; +GPUvisualVibration GPU_visualVibration; +GPUcursor GPU_cursor; +GPUaddVertex GPU_addVertex; + +CDRinit CDR_init; +CDRshutdown CDR_shutdown; +CDRopen CDR_open; +CDRclose CDR_close; +CDRtest CDR_test; +CDRgetTN CDR_getTN; +CDRgetTD CDR_getTD; +CDRreadTrack CDR_readTrack; +CDRgetBuffer CDR_getBuffer; +CDRplay CDR_play; +CDRstop CDR_stop; +CDRgetStatus CDR_getStatus; +CDRgetDriveLetter CDR_getDriveLetter; +CDRgetBufferSub CDR_getBufferSub; +CDRconfigure CDR_configure; +CDRabout CDR_about; +CDRsetfilename CDR_setfilename; +CDRreadCDDA CDR_readCDDA; +CDRgetTE CDR_getTE; + +SPUconfigure SPU_configure; +SPUabout SPU_about; +SPUinit SPU_init; +SPUshutdown SPU_shutdown; +SPUtest SPU_test; +SPUopen SPU_open; +SPUclose SPU_close; +SPUplaySample SPU_playSample; +SPUwriteRegister SPU_writeRegister; +SPUreadRegister SPU_readRegister; +SPUwriteDMA SPU_writeDMA; +SPUreadDMA SPU_readDMA; +SPUwriteDMAMem SPU_writeDMAMem; +SPUreadDMAMem SPU_readDMAMem; +SPUplayADPCMchannel SPU_playADPCMchannel; +SPUfreeze SPU_freeze; +SPUregisterCallback SPU_registerCallback; +SPUasync SPU_async; +SPUplayCDDAchannel SPU_playCDDAchannel; + +PADconfigure PAD1_configure; +PADabout PAD1_about; +PADinit PAD1_init; +PADshutdown PAD1_shutdown; +PADtest PAD1_test; +PADopen PAD1_open; +PADclose PAD1_close; +PADquery PAD1_query; +PADreadPort1 PAD1_readPort1; +PADkeypressed PAD1_keypressed; +PADstartPoll PAD1_startPoll; +PADpoll PAD1_poll; +PADsetSensitive PAD1_setSensitive; +PADregisterVibration PAD1_registerVibration; +PADregisterCursor PAD1_registerCursor; + +PADconfigure PAD2_configure; +PADabout PAD2_about; +PADinit PAD2_init; +PADshutdown PAD2_shutdown; +PADtest PAD2_test; +PADopen PAD2_open; +PADclose PAD2_close; +PADquery PAD2_query; +PADreadPort2 PAD2_readPort2; +PADkeypressed PAD2_keypressed; +PADstartPoll PAD2_startPoll; +PADpoll PAD2_poll; +PADsetSensitive PAD2_setSensitive; +PADregisterVibration PAD2_registerVibration; +PADregisterCursor PAD2_registerCursor; + +NETinit NET_init; +NETshutdown NET_shutdown; +NETopen NET_open; +NETclose NET_close; +NETtest NET_test; +NETconfigure NET_configure; +NETabout NET_about; +NETpause NET_pause; +NETresume NET_resume; +NETqueryPlayer NET_queryPlayer; +NETsendData NET_sendData; +NETrecvData NET_recvData; +NETsendPadData NET_sendPadData; +NETrecvPadData NET_recvPadData; +NETsetInfo NET_setInfo; +NETkeypressed NET_keypressed; + +#ifdef ENABLE_SIO1API + +SIO1init SIO1_init; +SIO1shutdown SIO1_shutdown; +SIO1open SIO1_open; +SIO1close SIO1_close; +SIO1test SIO1_test; +SIO1configure SIO1_configure; +SIO1about SIO1_about; +SIO1pause SIO1_pause; +SIO1resume SIO1_resume; +SIO1keypressed SIO1_keypressed; +SIO1writeData8 SIO1_writeData8; +SIO1writeData16 SIO1_writeData16; +SIO1writeData32 SIO1_writeData32; +SIO1writeStat16 SIO1_writeStat16; +SIO1writeStat32 SIO1_writeStat32; +SIO1writeMode16 SIO1_writeMode16; +SIO1writeMode32 SIO1_writeMode32; +SIO1writeCtrl16 SIO1_writeCtrl16; +SIO1writeCtrl32 SIO1_writeCtrl32; +SIO1writeBaud16 SIO1_writeBaud16; +SIO1writeBaud32 SIO1_writeBaud32; +SIO1readData8 SIO1_readData8; +SIO1readData16 SIO1_readData16; +SIO1readData32 SIO1_readData32; +SIO1readStat16 SIO1_readStat16; +SIO1readStat32 SIO1_readStat32; +SIO1readMode16 SIO1_readMode16; +SIO1readMode32 SIO1_readMode32; +SIO1readCtrl16 SIO1_readCtrl16; +SIO1readCtrl32 SIO1_readCtrl32; +SIO1readBaud16 SIO1_readBaud16; +SIO1readBaud32 SIO1_readBaud32; +SIO1registerCallback SIO1_registerCallback; + +#endif + +static const char *err; + +#define CheckErr(func) { \ + err = SysLibError(); \ + if (err != NULL) { SysMessage(_("Error loading %s: %s"), func, err); return -1; } \ +} + +#define LoadSym(dest, src, name, checkerr) { \ + dest = (src)SysLoadSym(drv, name); \ + if (checkerr) { CheckErr(name); } else SysLibError(); \ +} + +void *hGPUDriver = NULL; + +void CALLBACK GPU__displayText(char *pText) { + SysPrintf("%s\n", pText); +} + +long CALLBACK GPU__configure(void) { return 0; } +long CALLBACK GPU__test(void) { return 0; } +void CALLBACK GPU__about(void) {} +void CALLBACK GPU__makeSnapshot(void) {} +void CALLBACK GPU__keypressed(int key) {} +long CALLBACK GPU__getScreenPic(unsigned char *pMem) { return -1; } +long CALLBACK GPU__showScreenPic(unsigned char *pMem) { return -1; } +void CALLBACK GPU__clearDynarec(void (CALLBACK *callback)(void)) {} +void CALLBACK GPU__hSync(int val) {} +void CALLBACK GPU__vBlank(int val) {} +void CALLBACK GPU__visualVibration(unsigned long iSmall, unsigned long iBig) {} +void CALLBACK GPU__cursor(int player, int x, int y) {} +void CALLBACK GPU__addVertex(short sx,short sy,s64 fx,s64 fy,s64 fz) {} + +#define LoadGpuSym1(dest, name) \ + LoadSym(GPU_##dest, GPU##dest, name, TRUE); + +#define LoadGpuSym0(dest, name) \ + LoadSym(GPU_##dest, GPU##dest, name, FALSE); \ + if (GPU_##dest == NULL) GPU_##dest = (GPU##dest) GPU__##dest; + +#define LoadGpuSymN(dest, name) \ + LoadSym(GPU_##dest, GPU##dest, name, FALSE); + +static int LoadGPUplugin(const char *GPUdll) { + void *drv; + + hGPUDriver = SysLoadLibrary(GPUdll); + if (hGPUDriver == NULL) { + GPU_configure = NULL; + SysMessage (_("Could not load GPU plugin %s!"), GPUdll); return -1; + } + drv = hGPUDriver; + LoadGpuSym1(init, "GPUinit"); + LoadGpuSym1(shutdown, "GPUshutdown"); + LoadGpuSym1(open, "GPUopen"); + LoadGpuSym1(close, "GPUclose"); + LoadGpuSym1(readData, "GPUreadData"); + LoadGpuSym1(readDataMem, "GPUreadDataMem"); + LoadGpuSym1(readStatus, "GPUreadStatus"); + LoadGpuSym1(writeData, "GPUwriteData"); + LoadGpuSym1(writeDataMem, "GPUwriteDataMem"); + LoadGpuSym1(writeStatus, "GPUwriteStatus"); + LoadGpuSym1(dmaChain, "GPUdmaChain"); + LoadGpuSym1(updateLace, "GPUupdateLace"); + LoadGpuSym0(keypressed, "GPUkeypressed"); + LoadGpuSym0(displayText, "GPUdisplayText"); + LoadGpuSym0(makeSnapshot, "GPUmakeSnapshot"); + LoadGpuSym1(freeze, "GPUfreeze"); + LoadGpuSym0(getScreenPic, "GPUgetScreenPic"); + LoadGpuSym0(showScreenPic, "GPUshowScreenPic"); + LoadGpuSym0(clearDynarec, "GPUclearDynarec"); + LoadGpuSym0(hSync, "GPUhSync"); + LoadGpuSym0(vBlank, "GPUvBlank"); + LoadGpuSym0(visualVibration, "GPUvisualVibration"); + LoadGpuSym0(cursor, "GPUcursor"); + LoadGpuSym0(addVertex, "GPUaddVertex"); + LoadGpuSym0(configure, "GPUconfigure"); + LoadGpuSym0(test, "GPUtest"); + LoadGpuSym0(about, "GPUabout"); + + return 0; +} + +void *hCDRDriver = NULL; + +long CALLBACK CDR__play(unsigned char *sector) { return 0; } +long CALLBACK CDR__stop(void) { return 0; } + +long CALLBACK CDR__getStatus(struct CdrStat *stat) { + if (cdOpenCaseTime < 0 || cdOpenCaseTime > (s64)time(NULL)) + stat->Status = 0x10; + else + stat->Status = 0; + + return 0; +} + +char* CALLBACK CDR__getDriveLetter(void) { return NULL; } +long CALLBACK CDR__configure(void) { return 0; } +long CALLBACK CDR__test(void) { return 0; } +void CALLBACK CDR__about(void) {} +long CALLBACK CDR__setfilename(char*filename) { return 0; } + +#define LoadCdrSym1(dest, name) \ + LoadSym(CDR_##dest, CDR##dest, name, TRUE); + +#define LoadCdrSym0(dest, name) \ + LoadSym(CDR_##dest, CDR##dest, name, FALSE); \ + if (CDR_##dest == NULL) CDR_##dest = (CDR##dest) CDR__##dest; + +#define LoadCdrSymN(dest, name) \ + LoadSym(CDR_##dest, CDR##dest, name, FALSE); + +static int LoadCDRplugin(const char *CDRdll) { + void *drv; + + if (CDRdll == NULL) { + cdrIsoInit(); + return 0; + } + + hCDRDriver = SysLoadLibrary(CDRdll); + if (hCDRDriver == NULL) { + CDR_configure = NULL; + SysMessage (_("Could not load CD-ROM plugin %s!"), CDRdll); return -1; + } + drv = hCDRDriver; + LoadCdrSym1(init, "CDRinit"); + LoadCdrSym1(shutdown, "CDRshutdown"); + LoadCdrSym1(open, "CDRopen"); + LoadCdrSym1(close, "CDRclose"); + LoadCdrSym1(getTN, "CDRgetTN"); + LoadCdrSym1(getTD, "CDRgetTD"); + LoadCdrSym1(readTrack, "CDRreadTrack"); + LoadCdrSym1(getBuffer, "CDRgetBuffer"); + LoadCdrSym1(getBufferSub, "CDRgetBufferSub"); + LoadCdrSym0(play, "CDRplay"); + LoadCdrSym0(stop, "CDRstop"); + LoadCdrSym0(getStatus, "CDRgetStatus"); + LoadCdrSym0(getDriveLetter, "CDRgetDriveLetter"); + LoadCdrSym0(configure, "CDRconfigure"); + LoadCdrSym0(test, "CDRtest"); + LoadCdrSym0(about, "CDRabout"); + LoadCdrSym0(setfilename, "CDRsetfilename"); + LoadCdrSymN(readCDDA, "CDRreadCDDA"); + LoadCdrSymN(getTE, "CDRgetTE"); + + return 0; +} + +void *hSPUDriver = NULL; + +long CALLBACK SPU__configure(void) { return 0; } +void CALLBACK SPU__about(void) {} +long CALLBACK SPU__test(void) { return 0; } + +#define LoadSpuSym1(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, TRUE); + +#define LoadSpuSym0(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, FALSE); \ + if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest; + +#define LoadSpuSymN(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, FALSE); + +static int LoadSPUplugin(const char *SPUdll) { + void *drv; + + hSPUDriver = SysLoadLibrary(SPUdll); + if (hSPUDriver == NULL) { + SPU_configure = NULL; + SysMessage (_("Could not load SPU plugin %s!"), SPUdll); return -1; + } + drv = hSPUDriver; + LoadSpuSym1(init, "SPUinit"); + LoadSpuSym1(shutdown, "SPUshutdown"); + LoadSpuSym1(open, "SPUopen"); + LoadSpuSym1(close, "SPUclose"); + LoadSpuSym0(configure, "SPUconfigure"); + LoadSpuSym0(about, "SPUabout"); + LoadSpuSym0(test, "SPUtest"); + LoadSpuSym1(writeRegister, "SPUwriteRegister"); + LoadSpuSym1(readRegister, "SPUreadRegister"); + LoadSpuSym1(writeDMA, "SPUwriteDMA"); + LoadSpuSym1(readDMA, "SPUreadDMA"); + LoadSpuSym1(writeDMAMem, "SPUwriteDMAMem"); + LoadSpuSym1(readDMAMem, "SPUreadDMAMem"); + LoadSpuSym1(playADPCMchannel, "SPUplayADPCMchannel"); + LoadSpuSym1(freeze, "SPUfreeze"); + LoadSpuSym1(registerCallback, "SPUregisterCallback"); + LoadSpuSymN(async, "SPUasync"); + LoadSpuSymN(playCDDAchannel, "SPUplayCDDAchannel"); + + return 0; +} + +void *hPAD1Driver = NULL; +void *hPAD2Driver = NULL; + +static unsigned char buf[256]; +unsigned char stdpar[10] = { 0x00, 0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +unsigned char mousepar[8] = { 0x00, 0x12, 0x5a, 0xff, 0xff, 0xff, 0xff }; +unsigned char analogpar[9] = { 0x00, 0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +static int bufcount, bufc; + +PadDataS padd1, padd2; + +unsigned char _PADstartPoll(PadDataS *pad) { + bufc = 0; + + switch (pad->controllerType) { + case PSE_PAD_TYPE_MOUSE: + mousepar[3] = pad->buttonStatus & 0xff; + mousepar[4] = pad->buttonStatus >> 8; + mousepar[5] = pad->moveX; + mousepar[6] = pad->moveY; + + memcpy(buf, mousepar, 7); + bufcount = 6; + break; + case PSE_PAD_TYPE_NEGCON: // npc101/npc104(slph00001/slph00069) + analogpar[1] = 0x23; + analogpar[3] = pad->buttonStatus & 0xff; + analogpar[4] = pad->buttonStatus >> 8; + analogpar[5] = pad->rightJoyX; + analogpar[6] = pad->rightJoyY; + analogpar[7] = pad->leftJoyX; + analogpar[8] = pad->leftJoyY; + + memcpy(buf, analogpar, 9); + bufcount = 8; + break; + case PSE_PAD_TYPE_ANALOGPAD: // scph1150 + analogpar[1] = 0x73; + analogpar[3] = pad->buttonStatus & 0xff; + analogpar[4] = pad->buttonStatus >> 8; + analogpar[5] = pad->rightJoyX; + analogpar[6] = pad->rightJoyY; + analogpar[7] = pad->leftJoyX; + analogpar[8] = pad->leftJoyY; + + memcpy(buf, analogpar, 9); + bufcount = 8; + break; + case PSE_PAD_TYPE_ANALOGJOY: // scph1110 + analogpar[1] = 0x53; + analogpar[3] = pad->buttonStatus & 0xff; + analogpar[4] = pad->buttonStatus >> 8; + analogpar[5] = pad->rightJoyX; + analogpar[6] = pad->rightJoyY; + analogpar[7] = pad->leftJoyX; + analogpar[8] = pad->leftJoyY; + + memcpy(buf, analogpar, 9); + bufcount = 8; + break; + case PSE_PAD_TYPE_STANDARD: + default: + stdpar[3] = pad->buttonStatus & 0xff; + stdpar[4] = pad->buttonStatus >> 8; + + memcpy(buf, stdpar, 5); + bufcount = 4; + } + + return buf[bufc++]; +} + +unsigned char _PADpoll(unsigned char value) { + if (bufc > bufcount) return 0; + return buf[bufc++]; +} + +unsigned char CALLBACK PAD1__startPoll(int pad) { + PadDataS padd; + + PAD1_readPort1(&padd); + + return _PADstartPoll(&padd); +} + +unsigned char CALLBACK PAD1__poll(unsigned char value) { + return _PADpoll(value); +} + +long CALLBACK PAD1__configure(void) { return 0; } +void CALLBACK PAD1__about(void) {} +long CALLBACK PAD1__test(void) { return 0; } +long CALLBACK PAD1__query(void) { return 3; } +long CALLBACK PAD1__keypressed() { return 0; } +void CALLBACK PAD1__registerVibration(void (CALLBACK *callback)(unsigned long, unsigned long)) {} +void CALLBACK PAD1__registerCursor(void (CALLBACK *callback)(int, int, int)) {} + +#define LoadPad1Sym1(dest, name) \ + LoadSym(PAD1_##dest, PAD##dest, name, TRUE); + +#define LoadPad1SymN(dest, name) \ + LoadSym(PAD1_##dest, PAD##dest, name, FALSE); + +#define LoadPad1Sym0(dest, name) \ + LoadSym(PAD1_##dest, PAD##dest, name, FALSE); \ + if (PAD1_##dest == NULL) PAD1_##dest = (PAD##dest) PAD1__##dest; + +static int LoadPAD1plugin(const char *PAD1dll) { + void *drv; + + hPAD1Driver = SysLoadLibrary(PAD1dll); + if (hPAD1Driver == NULL) { + PAD1_configure = NULL; + SysMessage (_("Could not load Controller 1 plugin %s!"), PAD1dll); return -1; + } + drv = hPAD1Driver; + LoadPad1Sym1(init, "PADinit"); + LoadPad1Sym1(shutdown, "PADshutdown"); + LoadPad1Sym1(open, "PADopen"); + LoadPad1Sym1(close, "PADclose"); + LoadPad1Sym0(query, "PADquery"); + LoadPad1Sym1(readPort1, "PADreadPort1"); + LoadPad1Sym0(configure, "PADconfigure"); + LoadPad1Sym0(test, "PADtest"); + LoadPad1Sym0(about, "PADabout"); + LoadPad1Sym0(keypressed, "PADkeypressed"); + LoadPad1Sym0(startPoll, "PADstartPoll"); + LoadPad1Sym0(poll, "PADpoll"); + LoadPad1SymN(setSensitive, "PADsetSensitive"); + LoadPad1Sym0(registerVibration, "PADregisterVibration"); + LoadPad1Sym0(registerCursor, "PADregisterCursor"); + + return 0; +} + +unsigned char CALLBACK PAD2__startPoll(int pad) { + PadDataS padd; + + PAD2_readPort2(&padd); + + return _PADstartPoll(&padd); +} + +unsigned char CALLBACK PAD2__poll(unsigned char value) { + return _PADpoll(value); +} + +long CALLBACK PAD2__configure(void) { return 0; } +void CALLBACK PAD2__about(void) {} +long CALLBACK PAD2__test(void) { return 0; } +long CALLBACK PAD2__query(void) { return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; } +long CALLBACK PAD2__keypressed() { return 0; } +void CALLBACK PAD2__registerVibration(void (CALLBACK *callback)(unsigned long, unsigned long)) {} +void CALLBACK PAD2__registerCursor(void (CALLBACK *callback)(int, int, int)) {} + +#define LoadPad2Sym1(dest, name) \ + LoadSym(PAD2_##dest, PAD##dest, name, TRUE); + +#define LoadPad2Sym0(dest, name) \ + LoadSym(PAD2_##dest, PAD##dest, name, FALSE); \ + if (PAD2_##dest == NULL) PAD2_##dest = (PAD##dest) PAD2__##dest; + +#define LoadPad2SymN(dest, name) \ + LoadSym(PAD2_##dest, PAD##dest, name, FALSE); + +static int LoadPAD2plugin(const char *PAD2dll) { + void *drv; + + hPAD2Driver = SysLoadLibrary(PAD2dll); + if (hPAD2Driver == NULL) { + PAD2_configure = NULL; + SysMessage (_("Could not load Controller 2 plugin %s!"), PAD2dll); return -1; + } + drv = hPAD2Driver; + LoadPad2Sym1(init, "PADinit"); + LoadPad2Sym1(shutdown, "PADshutdown"); + LoadPad2Sym1(open, "PADopen"); + LoadPad2Sym1(close, "PADclose"); + LoadPad2Sym0(query, "PADquery"); + LoadPad2Sym1(readPort2, "PADreadPort2"); + LoadPad2Sym0(configure, "PADconfigure"); + LoadPad2Sym0(test, "PADtest"); + LoadPad2Sym0(about, "PADabout"); + LoadPad2Sym0(keypressed, "PADkeypressed"); + LoadPad2Sym0(startPoll, "PADstartPoll"); + LoadPad2Sym0(poll, "PADpoll"); + LoadPad2SymN(setSensitive, "PADsetSensitive"); + LoadPad2Sym0(registerVibration, "PADregisterVibration"); + LoadPad2Sym0(registerCursor, "PADregisterCursor"); + + return 0; +} + +void *hNETDriver = NULL; + +void CALLBACK NET__setInfo(netInfo *info) {} +void CALLBACK NET__keypressed(int key) {} +long CALLBACK NET__configure(void) { return 0; } +long CALLBACK NET__test(void) { return 0; } +void CALLBACK NET__about(void) {} + +#define LoadNetSym1(dest, name) \ + LoadSym(NET_##dest, NET##dest, name, TRUE); + +#define LoadNetSymN(dest, name) \ + LoadSym(NET_##dest, NET##dest, name, FALSE); + +#define LoadNetSym0(dest, name) \ + LoadSym(NET_##dest, NET##dest, name, FALSE); \ + if (NET_##dest == NULL) NET_##dest = (NET##dest) NET__##dest; + +static int LoadNETplugin(const char *NETdll) { + void *drv; + + hNETDriver = SysLoadLibrary(NETdll); + if (hNETDriver == NULL) { + SysMessage (_("Could not load NetPlay plugin %s!"), NETdll); return -1; + } + drv = hNETDriver; + LoadNetSym1(init, "NETinit"); + LoadNetSym1(shutdown, "NETshutdown"); + LoadNetSym1(open, "NETopen"); + LoadNetSym1(close, "NETclose"); + LoadNetSymN(sendData, "NETsendData"); + LoadNetSymN(recvData, "NETrecvData"); + LoadNetSym1(sendPadData, "NETsendPadData"); + LoadNetSym1(recvPadData, "NETrecvPadData"); + LoadNetSym1(queryPlayer, "NETqueryPlayer"); + LoadNetSym1(pause, "NETpause"); + LoadNetSym1(resume, "NETresume"); + LoadNetSym0(setInfo, "NETsetInfo"); + LoadNetSym0(keypressed, "NETkeypressed"); + LoadNetSym0(configure, "NETconfigure"); + LoadNetSym0(test, "NETtest"); + LoadNetSym0(about, "NETabout"); + + return 0; +} + +#ifdef ENABLE_SIO1API + +void *hSIO1Driver = NULL; + +long CALLBACK SIO1__init(void) { return 0; } +long CALLBACK SIO1__shutdown(void) { return 0; } +long CALLBACK SIO1__open(void) { return 0; } +long CALLBACK SIO1__close(void) { return 0; } +long CALLBACK SIO1__configure(void) { return 0; } +long CALLBACK SIO1__test(void) { return 0; } +void CALLBACK SIO1__about(void) {} +void CALLBACK SIO1__pause(void) {} +void CALLBACK SIO1__resume(void) {} +long CALLBACK SIO1__keypressed(int key) { return 0; } +void CALLBACK SIO1__writeData8(unsigned char val) {} +void CALLBACK SIO1__writeData16(unsigned short val) {} +void CALLBACK SIO1__writeData32(unsigned long val) {} +void CALLBACK SIO1__writeStat16(unsigned short val) {} +void CALLBACK SIO1__writeStat32(unsigned long val) {} +void CALLBACK SIO1__writeMode16(unsigned short val) {} +void CALLBACK SIO1__writeMode32(unsigned long val) {} +void CALLBACK SIO1__writeCtrl16(unsigned short val) {} +void CALLBACK SIO1__writeCtrl32(unsigned long val) {} +void CALLBACK SIO1__writeBaud16(unsigned short val) {} +void CALLBACK SIO1__writeBaud32(unsigned long val) {} +unsigned char CALLBACK SIO1__readData8(void) { return 0; } +unsigned short CALLBACK SIO1__readData16(void) { return 0; } +unsigned long CALLBACK SIO1__readData32(void) { return 0; } +unsigned short CALLBACK SIO1__readStat16(void) { return 0; } +unsigned long CALLBACK SIO1__readStat32(void) { return 0; } +unsigned short CALLBACK SIO1__readMode16(void) { return 0; } +unsigned long CALLBACK SIO1__readMode32(void) { return 0; } +unsigned short CALLBACK SIO1__readCtrl16(void) { return 0; } +unsigned long CALLBACK SIO1__readCtrl32(void) { return 0; } +unsigned short CALLBACK SIO1__readBaud16(void) { return 0; } +unsigned long CALLBACK SIO1__readBaud32(void) { return 0; } +void CALLBACK SIO1__registerCallback(void (CALLBACK *callback)(void)) {}; + +void CALLBACK SIO1irq(void) { + psxHu32ref(0x1070) |= SWAPu32(0x100); +} + +#define LoadSio1Sym1(dest, name) \ + LoadSym(SIO1_##dest, SIO1##dest, name, TRUE); + +#define LoadSio1SymN(dest, name) \ + LoadSym(SIO1_##dest, SIO1##dest, name, FALSE); + +#define LoadSio1Sym0(dest, name) \ + LoadSym(SIO1_##dest, SIO1##dest, name, FALSE); \ + if (SIO1_##dest == NULL) SIO1_##dest = (SIO1##dest) SIO1__##dest; + +static int LoadSIO1plugin(const char *SIO1dll) { + void *drv; + + hSIO1Driver = SysLoadLibrary(SIO1dll); + if (hSIO1Driver == NULL) { + SysMessage (_("Could not load SIO1 plugin %s!"), SIO1dll); return -1; + } + drv = hSIO1Driver; + + LoadSio1Sym0(init, "SIO1init"); + LoadSio1Sym0(shutdown, "SIO1shutdown"); + LoadSio1Sym0(open, "SIO1open"); + LoadSio1Sym0(close, "SIO1close"); + LoadSio1Sym0(pause, "SIO1pause"); + LoadSio1Sym0(resume, "SIO1resume"); + LoadSio1Sym0(keypressed, "SIO1keypressed"); + LoadSio1Sym0(configure, "SIO1configure"); + LoadSio1Sym0(test, "SIO1test"); + LoadSio1Sym0(about, "SIO1about"); + LoadSio1Sym0(writeData8, "SIO1writeData8"); + LoadSio1Sym0(writeData16, "SIO1writeData16"); + LoadSio1Sym0(writeData32, "SIO1writeData32"); + LoadSio1Sym0(writeStat16, "SIO1writeStat16"); + LoadSio1Sym0(writeStat32, "SIO1writeStat32"); + LoadSio1Sym0(writeMode16, "SIO1writeMode16"); + LoadSio1Sym0(writeMode32, "SIO1writeMode32"); + LoadSio1Sym0(writeCtrl16, "SIO1writeCtrl16"); + LoadSio1Sym0(writeCtrl32, "SIO1writeCtrl32"); + LoadSio1Sym0(writeBaud16, "SIO1writeBaud16"); + LoadSio1Sym0(writeBaud32, "SIO1writeBaud32"); + LoadSio1Sym0(readData16, "SIO1readData16"); + LoadSio1Sym0(readData32, "SIO1readData32"); + LoadSio1Sym0(readStat16, "SIO1readStat16"); + LoadSio1Sym0(readStat32, "SIO1readStat32"); + LoadSio1Sym0(readMode16, "SIO1readMode16"); + LoadSio1Sym0(readMode32, "SIO1readMode32"); + LoadSio1Sym0(readCtrl16, "SIO1readCtrl16"); + LoadSio1Sym0(readCtrl32, "SIO1readCtrl32"); + LoadSio1Sym0(readBaud16, "SIO1readBaud16"); + LoadSio1Sym0(readBaud32, "SIO1readBaud32"); + LoadSio1Sym0(registerCallback, "SIO1registerCallback"); + + return 0; +} + +#endif + +void CALLBACK clearDynarec(void) { + psxCpu->Reset(); +} + +int LoadPlugins() { + int ret; + char Plugin[MAXPATHLEN]; + + ReleasePlugins(); + + if (UsingIso()) { + LoadCDRplugin(NULL); + } else { + sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr); + if (LoadCDRplugin(Plugin) == -1) return -1; + } + + sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Gpu); + if (LoadGPUplugin(Plugin) == -1) return -1; + + sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Spu); + if (LoadSPUplugin(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; + + if (strcmp("Disabled", Config.Net) == 0 || strcmp("", Config.Net) == 0) + Config.UseNet = FALSE; + else { + Config.UseNet = TRUE; + sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Net); + if (LoadNETplugin(Plugin) == -1) Config.UseNet = FALSE; + } + +#ifdef ENABLE_SIO1API + sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Sio1); + if (LoadSIO1plugin(Plugin) == -1) return -1; +#endif + + ret = CDR_init(); + if (ret < 0) { SysMessage (_("Error initializing CD-ROM plugin: %d"), ret); return -1; } + ret = GPU_init(); + if (ret < 0) { SysMessage (_("Error initializing GPU plugin: %d"), ret); return -1; } + ret = SPU_init(); + if (ret < 0) { SysMessage (_("Error initializing SPU plugin: %d"), ret); return -1; } + ret = PAD1_init(1); + if (ret < 0) { SysMessage (_("Error initializing Controller 1 plugin: %d"), ret); return -1; } + ret = PAD2_init(2); + if (ret < 0) { SysMessage (_("Error initializing Controller 2 plugin: %d"), ret); return -1; } + + if (Config.UseNet) { + ret = NET_init(); + if (ret < 0) { SysMessage (_("Error initializing NetPlay plugin: %d"), ret); return -1; } + } + +#ifdef ENABLE_SIO1API + ret = SIO1_init(); + if (ret < 0) { SysMessage (_("Error initializing SIO1 plugin: %d"), ret); return -1; } +#endif + + SysPrintf(_("Plugins loaded.\n")); + return 0; +} + +void ReleasePlugins() { + if (Config.UseNet) { + int ret = NET_close(); + if (ret < 0) Config.UseNet = FALSE; + } + NetOpened = FALSE; + + if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown(); + if (hGPUDriver != NULL) GPU_shutdown(); + if (hSPUDriver != NULL) SPU_shutdown(); + if (hPAD1Driver != NULL) PAD1_shutdown(); + if (hPAD2Driver != NULL) PAD2_shutdown(); + + if (Config.UseNet && hNETDriver != NULL) NET_shutdown(); + + if (hCDRDriver != NULL) SysCloseLibrary(hCDRDriver); hCDRDriver = NULL; + if (hGPUDriver != NULL) SysCloseLibrary(hGPUDriver); hGPUDriver = NULL; + if (hSPUDriver != NULL) SysCloseLibrary(hSPUDriver); hSPUDriver = NULL; + if (hPAD1Driver != NULL) SysCloseLibrary(hPAD1Driver); hPAD1Driver = NULL; + if (hPAD2Driver != NULL) SysCloseLibrary(hPAD2Driver); hPAD2Driver = NULL; + + if (Config.UseNet && hNETDriver != NULL) { + SysCloseLibrary(hNETDriver); hNETDriver = NULL; + } + +#ifdef ENABLE_SIO1API + if (hSIO1Driver != NULL) { + SIO1_shutdown(); + SysCloseLibrary(hSIO1Driver); + hSIO1Driver = NULL; + } +#endif +} + +void SetIsoFile(const char *filename) { + if (filename == NULL) { + IsoFile[0] = '\0'; + return; + } + strncpy(IsoFile, filename, MAXPATHLEN); +} + +const char *GetIsoFile(void) { + return IsoFile; +} + +boolean UsingIso(void) { + return (IsoFile[0] != '\0'); +} + +void SetCdOpenCaseTime(s64 time) { + cdOpenCaseTime = time; +} diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index 3247c752..5d6aa9d2 100644..100755 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -1,424 +1,424 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#ifndef __PLUGINS_H__
-#define __PLUGINS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "psxcommon.h"
-
-//#define ENABLE_SIO1API 1
-
-#ifndef _WIN32
-
-typedef void* HWND;
-#define CALLBACK
-
-typedef long (*GPUopen)(unsigned long *, char *, char *);
-typedef long (*SPUopen)(void);
-typedef long (*PADopen)(unsigned long *);
-typedef long (*NETopen)(unsigned long *);
-typedef long (*SIO1open)(unsigned long *);
-
-#else
-
-#include <windows.h>
-
-typedef long (CALLBACK* GPUopen)(HWND);
-typedef long (CALLBACK* SPUopen)(HWND);
-typedef long (CALLBACK* PADopen)(HWND);
-typedef long (CALLBACK* NETopen)(HWND);
-typedef long (CALLBACK* SIO1open)(HWND);
-
-#endif
-
-#include "spu.h"
-
-#include "psemu_plugin_defs.h"
-#include "decode_xa.h"
-
-int LoadPlugins();
-void ReleasePlugins();
-int OpenPlugins();
-void ClosePlugins();
-
-typedef unsigned long (CALLBACK* PSEgetLibType)(void);
-typedef unsigned long (CALLBACK* PSEgetLibVersion)(void);
-typedef char *(CALLBACK* PSEgetLibName)(void);
-
-// GPU Functions
-typedef long (CALLBACK* GPUinit)(void);
-typedef long (CALLBACK* GPUshutdown)(void);
-typedef long (CALLBACK* GPUclose)(void);
-typedef void (CALLBACK* GPUwriteStatus)(uint32_t);
-typedef void (CALLBACK* GPUwriteData)(uint32_t);
-typedef void (CALLBACK* GPUwriteDataMem)(uint32_t *, int);
-typedef uint32_t (CALLBACK* GPUreadStatus)(void);
-typedef uint32_t (CALLBACK* GPUreadData)(void);
-typedef void (CALLBACK* GPUreadDataMem)(uint32_t *, int);
-typedef long (CALLBACK* GPUdmaChain)(uint32_t *,uint32_t);
-typedef void (CALLBACK* GPUupdateLace)(void);
-typedef long (CALLBACK* GPUconfigure)(void);
-typedef long (CALLBACK* GPUtest)(void);
-typedef void (CALLBACK* GPUabout)(void);
-typedef void (CALLBACK* GPUmakeSnapshot)(void);
-typedef void (CALLBACK* GPUkeypressed)(int);
-typedef void (CALLBACK* GPUdisplayText)(char *);
-typedef struct {
- uint32_t ulFreezeVersion;
- uint32_t ulStatus;
- uint32_t ulControl[256];
- unsigned char psxVRam[1024*512*2];
-} GPUFreeze_t;
-typedef long (CALLBACK* GPUfreeze)(uint32_t, GPUFreeze_t *);
-typedef long (CALLBACK* GPUgetScreenPic)(unsigned char *);
-typedef long (CALLBACK* GPUshowScreenPic)(unsigned char *);
-typedef void (CALLBACK* GPUclearDynarec)(void (CALLBACK *callback)(void));
-typedef void (CALLBACK* GPUhSync)(int);
-typedef void (CALLBACK* GPUvBlank)(int);
-typedef void (CALLBACK* GPUvisualVibration)(uint32_t, uint32_t);
-typedef void (CALLBACK* GPUcursor)(int, int, int);
-typedef void (CALLBACK* GPUaddVertex)(short,short,s64,s64,s64);
-
-// GPU function pointers
-extern GPUupdateLace GPU_updateLace;
-extern GPUinit GPU_init;
-extern GPUshutdown GPU_shutdown;
-extern GPUconfigure GPU_configure;
-extern GPUtest GPU_test;
-extern GPUabout GPU_about;
-extern GPUopen GPU_open;
-extern GPUclose GPU_close;
-extern GPUreadStatus GPU_readStatus;
-extern GPUreadData GPU_readData;
-extern GPUreadDataMem GPU_readDataMem;
-extern GPUwriteStatus GPU_writeStatus;
-extern GPUwriteData GPU_writeData;
-extern GPUwriteDataMem GPU_writeDataMem;
-extern GPUdmaChain GPU_dmaChain;
-extern GPUkeypressed GPU_keypressed;
-extern GPUdisplayText GPU_displayText;
-extern GPUmakeSnapshot GPU_makeSnapshot;
-extern GPUfreeze GPU_freeze;
-extern GPUgetScreenPic GPU_getScreenPic;
-extern GPUshowScreenPic GPU_showScreenPic;
-extern GPUclearDynarec GPU_clearDynarec;
-extern GPUhSync GPU_hSync;
-extern GPUvBlank GPU_vBlank;
-extern GPUvisualVibration GPU_visualVibration;
-extern GPUcursor GPU_cursor;
-extern GPUaddVertex GPU_addVertex;
-
-// CD-ROM Functions
-typedef long (CALLBACK* CDRinit)(void);
-typedef long (CALLBACK* CDRshutdown)(void);
-typedef long (CALLBACK* CDRopen)(void);
-typedef long (CALLBACK* CDRclose)(void);
-typedef long (CALLBACK* CDRgetTN)(unsigned char *);
-typedef long (CALLBACK* CDRgetTD)(unsigned char, unsigned char *);
-typedef long (CALLBACK* CDRreadTrack)(unsigned char *);
-typedef unsigned char* (CALLBACK* CDRgetBuffer)(void);
-typedef unsigned char* (CALLBACK* CDRgetBufferSub)(void);
-typedef long (CALLBACK* CDRconfigure)(void);
-typedef long (CALLBACK* CDRtest)(void);
-typedef void (CALLBACK* CDRabout)(void);
-typedef long (CALLBACK* CDRplay)(unsigned char *);
-typedef long (CALLBACK* CDRstop)(void);
-typedef long (CALLBACK* CDRsetfilename)(char *);
-struct CdrStat {
- uint32_t Type;
- uint32_t Status;
- unsigned char Time[3];
-};
-typedef long (CALLBACK* CDRgetStatus)(struct CdrStat *);
-typedef char* (CALLBACK* CDRgetDriveLetter)(void);
-struct SubQ {
- char res0[12];
- unsigned char ControlAndADR;
- unsigned char TrackNumber;
- unsigned char IndexNumber;
- unsigned char TrackRelativeAddress[3];
- unsigned char Filler;
- unsigned char AbsoluteAddress[3];
- unsigned char CRC[2];
- char res1[72];
-};
-typedef long (CALLBACK* CDRreadCDDA)(unsigned char, unsigned char, unsigned char, unsigned char *);
-typedef long (CALLBACK* CDRgetTE)(unsigned char, unsigned char *, unsigned char *, unsigned char *);
-
-// CD-ROM function pointers
-extern CDRinit CDR_init;
-extern CDRshutdown CDR_shutdown;
-extern CDRopen CDR_open;
-extern CDRclose CDR_close;
-extern CDRtest CDR_test;
-extern CDRgetTN CDR_getTN;
-extern CDRgetTD CDR_getTD;
-extern CDRreadTrack CDR_readTrack;
-extern CDRgetBuffer CDR_getBuffer;
-extern CDRgetBufferSub CDR_getBufferSub;
-extern CDRplay CDR_play;
-extern CDRstop CDR_stop;
-extern CDRgetStatus CDR_getStatus;
-extern CDRgetDriveLetter CDR_getDriveLetter;
-extern CDRconfigure CDR_configure;
-extern CDRabout CDR_about;
-extern CDRsetfilename CDR_setfilename;
-extern CDRreadCDDA CDR_readCDDA;
-extern CDRgetTE CDR_getTE;
-
-// SPU Functions
-typedef long (CALLBACK* SPUinit)(void);
-typedef long (CALLBACK* SPUshutdown)(void);
-typedef long (CALLBACK* SPUclose)(void);
-typedef void (CALLBACK* SPUplaySample)(unsigned char);
-typedef void (CALLBACK* SPUwriteRegister)(unsigned long, unsigned short);
-typedef unsigned short (CALLBACK* SPUreadRegister)(unsigned long);
-typedef void (CALLBACK* SPUwriteDMA)(unsigned short);
-typedef unsigned short (CALLBACK* SPUreadDMA)(void);
-typedef void (CALLBACK* SPUwriteDMAMem)(unsigned short *, int);
-typedef void (CALLBACK* SPUreadDMAMem)(unsigned short *, int);
-typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *);
-typedef void (CALLBACK* SPUregisterCallback)(void (CALLBACK *callback)(void));
-typedef long (CALLBACK* SPUconfigure)(void);
-typedef long (CALLBACK* SPUtest)(void);
-typedef void (CALLBACK* SPUabout)(void);
-typedef struct {
- unsigned char PluginName[8];
- uint32_t PluginVersion;
- uint32_t Size;
- unsigned char SPUPorts[0x200];
- unsigned char SPURam[0x80000];
- xa_decode_t xa;
- unsigned char *SPUInfo;
-} SPUFreeze_t;
-typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *);
-typedef void (CALLBACK* SPUasync)(uint32_t);
-typedef void (CALLBACK* SPUplayCDDAchannel)(short *, int);
-
-// SPU function pointers
-extern SPUconfigure SPU_configure;
-extern SPUabout SPU_about;
-extern SPUinit SPU_init;
-extern SPUshutdown SPU_shutdown;
-extern SPUtest SPU_test;
-extern SPUopen SPU_open;
-extern SPUclose SPU_close;
-extern SPUplaySample SPU_playSample;
-extern SPUwriteRegister SPU_writeRegister;
-extern SPUreadRegister SPU_readRegister;
-extern SPUwriteDMA SPU_writeDMA;
-extern SPUreadDMA SPU_readDMA;
-extern SPUwriteDMAMem SPU_writeDMAMem;
-extern SPUreadDMAMem SPU_readDMAMem;
-extern SPUplayADPCMchannel SPU_playADPCMchannel;
-extern SPUfreeze SPU_freeze;
-extern SPUregisterCallback SPU_registerCallback;
-extern SPUasync SPU_async;
-extern SPUplayCDDAchannel SPU_playCDDAchannel;
-
-// PAD Functions
-typedef long (CALLBACK* PADconfigure)(void);
-typedef void (CALLBACK* PADabout)(void);
-typedef long (CALLBACK* PADinit)(long);
-typedef long (CALLBACK* PADshutdown)(void);
-typedef long (CALLBACK* PADtest)(void);
-typedef long (CALLBACK* PADclose)(void);
-typedef long (CALLBACK* PADquery)(void);
-typedef long (CALLBACK* PADreadPort1)(PadDataS*);
-typedef long (CALLBACK* PADreadPort2)(PadDataS*);
-typedef long (CALLBACK* PADkeypressed)(void);
-typedef unsigned char (CALLBACK* PADstartPoll)(int);
-typedef unsigned char (CALLBACK* PADpoll)(unsigned char);
-typedef void (CALLBACK* PADsetSensitive)(int);
-typedef void (CALLBACK* PADregisterVibration)(void (CALLBACK *callback)(uint32_t, uint32_t));
-typedef void (CALLBACK* PADregisterCursor)(void (CALLBACK *callback)(int, int, int));
-
-// PAD function pointers
-extern PADconfigure PAD1_configure;
-extern PADabout PAD1_about;
-extern PADinit PAD1_init;
-extern PADshutdown PAD1_shutdown;
-extern PADtest PAD1_test;
-extern PADopen PAD1_open;
-extern PADclose PAD1_close;
-extern PADquery PAD1_query;
-extern PADreadPort1 PAD1_readPort1;
-extern PADkeypressed PAD1_keypressed;
-extern PADstartPoll PAD1_startPoll;
-extern PADpoll PAD1_poll;
-extern PADsetSensitive PAD1_setSensitive;
-extern PADregisterVibration PAD1_registerVibration;
-extern PADregisterCursor PAD1_registerCursor;
-extern PADconfigure PAD2_configure;
-extern PADabout PAD2_about;
-extern PADinit PAD2_init;
-extern PADshutdown PAD2_shutdown;
-extern PADtest PAD2_test;
-extern PADopen PAD2_open;
-extern PADclose PAD2_close;
-extern PADquery PAD2_query;
-extern PADreadPort2 PAD2_readPort2;
-extern PADkeypressed PAD2_keypressed;
-extern PADstartPoll PAD2_startPoll;
-extern PADpoll PAD2_poll;
-extern PADsetSensitive PAD2_setSensitive;
-extern PADregisterVibration PAD2_registerVibration;
-extern PADregisterCursor PAD2_registerCursor;
-
-// NET Functions
-typedef long (CALLBACK* NETinit)(void);
-typedef long (CALLBACK* NETshutdown)(void);
-typedef long (CALLBACK* NETclose)(void);
-typedef long (CALLBACK* NETconfigure)(void);
-typedef long (CALLBACK* NETtest)(void);
-typedef void (CALLBACK* NETabout)(void);
-typedef void (CALLBACK* NETpause)(void);
-typedef void (CALLBACK* NETresume)(void);
-typedef long (CALLBACK* NETqueryPlayer)(void);
-typedef long (CALLBACK* NETsendData)(void *, int, int);
-typedef long (CALLBACK* NETrecvData)(void *, int, int);
-typedef long (CALLBACK* NETsendPadData)(void *, int);
-typedef long (CALLBACK* NETrecvPadData)(void *, int);
-
-typedef struct {
- char EmuName[32];
- char CdromID[9]; // ie. 'SCPH12345', no \0 trailing character
- char CdromLabel[11];
- void *psxMem;
- GPUshowScreenPic GPU_showScreenPic;
- GPUdisplayText GPU_displayText;
- PADsetSensitive PAD_setSensitive;
- char GPUpath[256]; // paths must be absolute
- char SPUpath[256];
- char CDRpath[256];
- char MCD1path[256];
- char MCD2path[256];
- char BIOSpath[256]; // 'HLE' for internal bios
- char Unused[1024];
-} netInfo;
-
-typedef long (CALLBACK* NETsetInfo)(netInfo *);
-typedef long (CALLBACK* NETkeypressed)(int);
-
-// NET function pointers
-extern NETinit NET_init;
-extern NETshutdown NET_shutdown;
-extern NETopen NET_open;
-extern NETclose NET_close;
-extern NETtest NET_test;
-extern NETconfigure NET_configure;
-extern NETabout NET_about;
-extern NETpause NET_pause;
-extern NETresume NET_resume;
-extern NETqueryPlayer NET_queryPlayer;
-extern NETsendData NET_sendData;
-extern NETrecvData NET_recvData;
-extern NETsendPadData NET_sendPadData;
-extern NETrecvPadData NET_recvPadData;
-extern NETsetInfo NET_setInfo;
-extern NETkeypressed NET_keypressed;
-
-#ifdef ENABLE_SIO1API
-
-// SIO1 Functions (link cable)
-typedef long (CALLBACK* SIO1init)(void);
-typedef long (CALLBACK* SIO1shutdown)(void);
-typedef long (CALLBACK* SIO1close)(void);
-typedef long (CALLBACK* SIO1configure)(void);
-typedef long (CALLBACK* SIO1test)(void);
-typedef void (CALLBACK* SIO1about)(void);
-typedef void (CALLBACK* SIO1pause)(void);
-typedef void (CALLBACK* SIO1resume)(void);
-typedef long (CALLBACK* SIO1keypressed)(int);
-typedef void (CALLBACK* SIO1writeData8)(unsigned char);
-typedef void (CALLBACK* SIO1writeData16)(unsigned short);
-typedef void (CALLBACK* SIO1writeData32)(unsigned long);
-typedef void (CALLBACK* SIO1writeStat16)(unsigned short);
-typedef void (CALLBACK* SIO1writeStat32)(unsigned long);
-typedef void (CALLBACK* SIO1writeMode16)(unsigned short);
-typedef void (CALLBACK* SIO1writeMode32)(unsigned long);
-typedef void (CALLBACK* SIO1writeCtrl16)(unsigned short);
-typedef void (CALLBACK* SIO1writeCtrl32)(unsigned long);
-typedef void (CALLBACK* SIO1writeBaud16)(unsigned short);
-typedef void (CALLBACK* SIO1writeBaud32)(unsigned long);
-typedef unsigned char (CALLBACK* SIO1readData8)(void);
-typedef unsigned short (CALLBACK* SIO1readData16)(void);
-typedef unsigned long (CALLBACK* SIO1readData32)(void);
-typedef unsigned short (CALLBACK* SIO1readStat16)(void);
-typedef unsigned long (CALLBACK* SIO1readStat32)(void);
-typedef unsigned short (CALLBACK* SIO1readMode16)(void);
-typedef unsigned long (CALLBACK* SIO1readMode32)(void);
-typedef unsigned short (CALLBACK* SIO1readCtrl16)(void);
-typedef unsigned long (CALLBACK* SIO1readCtrl32)(void);
-typedef unsigned short (CALLBACK* SIO1readBaud16)(void);
-typedef unsigned long (CALLBACK* SIO1readBaud32)(void);
-typedef void (CALLBACK* SIO1registerCallback)(void (CALLBACK *callback)(void));
-
-// SIO1 function pointers
-extern SIO1init SIO1_init;
-extern SIO1shutdown SIO1_shutdown;
-extern SIO1open SIO1_open;
-extern SIO1close SIO1_close;
-extern SIO1test SIO1_test;
-extern SIO1configure SIO1_configure;
-extern SIO1about SIO1_about;
-extern SIO1pause SIO1_pause;
-extern SIO1resume SIO1_resume;
-extern SIO1keypressed SIO1_keypressed;
-extern SIO1writeData8 SIO1_writeData8;
-extern SIO1writeData16 SIO1_writeData16;
-extern SIO1writeData32 SIO1_writeData32;
-extern SIO1writeStat16 SIO1_writeStat16;
-extern SIO1writeStat32 SIO1_writeStat32;
-extern SIO1writeMode16 SIO1_writeMode16;
-extern SIO1writeMode32 SIO1_writeMode32;
-extern SIO1writeCtrl16 SIO1_writeCtrl16;
-extern SIO1writeCtrl32 SIO1_writeCtrl32;
-extern SIO1writeBaud16 SIO1_writeBaud16;
-extern SIO1writeBaud32 SIO1_writeBaud32;
-extern SIO1readData8 SIO1_readData8;
-extern SIO1readData16 SIO1_readData16;
-extern SIO1readData32 SIO1_readData32;
-extern SIO1readStat16 SIO1_readStat16;
-extern SIO1readStat32 SIO1_readStat32;
-extern SIO1readMode16 SIO1_readMode16;
-extern SIO1readMode32 SIO1_readMode32;
-extern SIO1readCtrl16 SIO1_readCtrl16;
-extern SIO1readCtrl32 SIO1_readCtrl32;
-extern SIO1readBaud16 SIO1_readBaud16;
-extern SIO1readBaud32 SIO1_readBaud32;
-extern SIO1registerCallback SIO1_registerCallback;
-
-#endif
-
-void CALLBACK clearDynarec(void);
-
-void SetIsoFile(const char *filename);
-const char *GetIsoFile(void);
-boolean UsingIso(void);
-void SetCdOpenCaseTime(s64 time);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef __PLUGINS_H__ +#define __PLUGINS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psxcommon.h" + +//#define ENABLE_SIO1API 1 + +#ifndef _WIN32 + +typedef void* HWND; +#define CALLBACK + +typedef long (*GPUopen)(unsigned long *, char *, char *); +typedef long (*SPUopen)(void); +typedef long (*PADopen)(unsigned long *); +typedef long (*NETopen)(unsigned long *); +typedef long (*SIO1open)(unsigned long *); + +#else + +#include <windows.h> + +typedef long (CALLBACK* GPUopen)(HWND); +typedef long (CALLBACK* SPUopen)(HWND); +typedef long (CALLBACK* PADopen)(HWND); +typedef long (CALLBACK* NETopen)(HWND); +typedef long (CALLBACK* SIO1open)(HWND); + +#endif + +#include "spu.h" + +#include "psemu_plugin_defs.h" +#include "decode_xa.h" + +int LoadPlugins(); +void ReleasePlugins(); +int OpenPlugins(); +void ClosePlugins(); + +typedef unsigned long (CALLBACK* PSEgetLibType)(void); +typedef unsigned long (CALLBACK* PSEgetLibVersion)(void); +typedef char *(CALLBACK* PSEgetLibName)(void); + +// GPU Functions +typedef long (CALLBACK* GPUinit)(void); +typedef long (CALLBACK* GPUshutdown)(void); +typedef long (CALLBACK* GPUclose)(void); +typedef void (CALLBACK* GPUwriteStatus)(uint32_t); +typedef void (CALLBACK* GPUwriteData)(uint32_t); +typedef void (CALLBACK* GPUwriteDataMem)(uint32_t *, int); +typedef uint32_t (CALLBACK* GPUreadStatus)(void); +typedef uint32_t (CALLBACK* GPUreadData)(void); +typedef void (CALLBACK* GPUreadDataMem)(uint32_t *, int); +typedef long (CALLBACK* GPUdmaChain)(uint32_t *,uint32_t); +typedef void (CALLBACK* GPUupdateLace)(void); +typedef long (CALLBACK* GPUconfigure)(void); +typedef long (CALLBACK* GPUtest)(void); +typedef void (CALLBACK* GPUabout)(void); +typedef void (CALLBACK* GPUmakeSnapshot)(void); +typedef void (CALLBACK* GPUkeypressed)(int); +typedef void (CALLBACK* GPUdisplayText)(char *); +typedef struct { + uint32_t ulFreezeVersion; + uint32_t ulStatus; + uint32_t ulControl[256]; + unsigned char psxVRam[1024*512*2]; +} GPUFreeze_t; +typedef long (CALLBACK* GPUfreeze)(uint32_t, GPUFreeze_t *); +typedef long (CALLBACK* GPUgetScreenPic)(unsigned char *); +typedef long (CALLBACK* GPUshowScreenPic)(unsigned char *); +typedef void (CALLBACK* GPUclearDynarec)(void (CALLBACK *callback)(void)); +typedef void (CALLBACK* GPUhSync)(int); +typedef void (CALLBACK* GPUvBlank)(int); +typedef void (CALLBACK* GPUvisualVibration)(uint32_t, uint32_t); +typedef void (CALLBACK* GPUcursor)(int, int, int); +typedef void (CALLBACK* GPUaddVertex)(short,short,s64,s64,s64); + +// GPU function pointers +extern GPUupdateLace GPU_updateLace; +extern GPUinit GPU_init; +extern GPUshutdown GPU_shutdown; +extern GPUconfigure GPU_configure; +extern GPUtest GPU_test; +extern GPUabout GPU_about; +extern GPUopen GPU_open; +extern GPUclose GPU_close; +extern GPUreadStatus GPU_readStatus; +extern GPUreadData GPU_readData; +extern GPUreadDataMem GPU_readDataMem; +extern GPUwriteStatus GPU_writeStatus; +extern GPUwriteData GPU_writeData; +extern GPUwriteDataMem GPU_writeDataMem; +extern GPUdmaChain GPU_dmaChain; +extern GPUkeypressed GPU_keypressed; +extern GPUdisplayText GPU_displayText; +extern GPUmakeSnapshot GPU_makeSnapshot; +extern GPUfreeze GPU_freeze; +extern GPUgetScreenPic GPU_getScreenPic; +extern GPUshowScreenPic GPU_showScreenPic; +extern GPUclearDynarec GPU_clearDynarec; +extern GPUhSync GPU_hSync; +extern GPUvBlank GPU_vBlank; +extern GPUvisualVibration GPU_visualVibration; +extern GPUcursor GPU_cursor; +extern GPUaddVertex GPU_addVertex; + +// CD-ROM Functions +typedef long (CALLBACK* CDRinit)(void); +typedef long (CALLBACK* CDRshutdown)(void); +typedef long (CALLBACK* CDRopen)(void); +typedef long (CALLBACK* CDRclose)(void); +typedef long (CALLBACK* CDRgetTN)(unsigned char *); +typedef long (CALLBACK* CDRgetTD)(unsigned char, unsigned char *); +typedef long (CALLBACK* CDRreadTrack)(unsigned char *); +typedef unsigned char* (CALLBACK* CDRgetBuffer)(void); +typedef unsigned char* (CALLBACK* CDRgetBufferSub)(void); +typedef long (CALLBACK* CDRconfigure)(void); +typedef long (CALLBACK* CDRtest)(void); +typedef void (CALLBACK* CDRabout)(void); +typedef long (CALLBACK* CDRplay)(unsigned char *); +typedef long (CALLBACK* CDRstop)(void); +typedef long (CALLBACK* CDRsetfilename)(char *); +struct CdrStat { + uint32_t Type; + uint32_t Status; + unsigned char Time[3]; +}; +typedef long (CALLBACK* CDRgetStatus)(struct CdrStat *); +typedef char* (CALLBACK* CDRgetDriveLetter)(void); +struct SubQ { + char res0[12]; + unsigned char ControlAndADR; + unsigned char TrackNumber; + unsigned char IndexNumber; + unsigned char TrackRelativeAddress[3]; + unsigned char Filler; + unsigned char AbsoluteAddress[3]; + unsigned char CRC[2]; + char res1[72]; +}; +typedef long (CALLBACK* CDRreadCDDA)(unsigned char, unsigned char, unsigned char, unsigned char *); +typedef long (CALLBACK* CDRgetTE)(unsigned char, unsigned char *, unsigned char *, unsigned char *); + +// CD-ROM function pointers +extern CDRinit CDR_init; +extern CDRshutdown CDR_shutdown; +extern CDRopen CDR_open; +extern CDRclose CDR_close; +extern CDRtest CDR_test; +extern CDRgetTN CDR_getTN; +extern CDRgetTD CDR_getTD; +extern CDRreadTrack CDR_readTrack; +extern CDRgetBuffer CDR_getBuffer; +extern CDRgetBufferSub CDR_getBufferSub; +extern CDRplay CDR_play; +extern CDRstop CDR_stop; +extern CDRgetStatus CDR_getStatus; +extern CDRgetDriveLetter CDR_getDriveLetter; +extern CDRconfigure CDR_configure; +extern CDRabout CDR_about; +extern CDRsetfilename CDR_setfilename; +extern CDRreadCDDA CDR_readCDDA; +extern CDRgetTE CDR_getTE; + +// SPU Functions +typedef long (CALLBACK* SPUinit)(void); +typedef long (CALLBACK* SPUshutdown)(void); +typedef long (CALLBACK* SPUclose)(void); +typedef void (CALLBACK* SPUplaySample)(unsigned char); +typedef void (CALLBACK* SPUwriteRegister)(unsigned long, unsigned short); +typedef unsigned short (CALLBACK* SPUreadRegister)(unsigned long); +typedef void (CALLBACK* SPUwriteDMA)(unsigned short); +typedef unsigned short (CALLBACK* SPUreadDMA)(void); +typedef void (CALLBACK* SPUwriteDMAMem)(unsigned short *, int); +typedef void (CALLBACK* SPUreadDMAMem)(unsigned short *, int); +typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *); +typedef void (CALLBACK* SPUregisterCallback)(void (CALLBACK *callback)(void)); +typedef long (CALLBACK* SPUconfigure)(void); +typedef long (CALLBACK* SPUtest)(void); +typedef void (CALLBACK* SPUabout)(void); +typedef struct { + unsigned char PluginName[8]; + uint32_t PluginVersion; + uint32_t Size; + unsigned char SPUPorts[0x200]; + unsigned char SPURam[0x80000]; + xa_decode_t xa; + unsigned char *SPUInfo; +} SPUFreeze_t; +typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *); +typedef void (CALLBACK* SPUasync)(uint32_t); +typedef void (CALLBACK* SPUplayCDDAchannel)(short *, int); + +// SPU function pointers +extern SPUconfigure SPU_configure; +extern SPUabout SPU_about; +extern SPUinit SPU_init; +extern SPUshutdown SPU_shutdown; +extern SPUtest SPU_test; +extern SPUopen SPU_open; +extern SPUclose SPU_close; +extern SPUplaySample SPU_playSample; +extern SPUwriteRegister SPU_writeRegister; +extern SPUreadRegister SPU_readRegister; +extern SPUwriteDMA SPU_writeDMA; +extern SPUreadDMA SPU_readDMA; +extern SPUwriteDMAMem SPU_writeDMAMem; +extern SPUreadDMAMem SPU_readDMAMem; +extern SPUplayADPCMchannel SPU_playADPCMchannel; +extern SPUfreeze SPU_freeze; +extern SPUregisterCallback SPU_registerCallback; +extern SPUasync SPU_async; +extern SPUplayCDDAchannel SPU_playCDDAchannel; + +// PAD Functions +typedef long (CALLBACK* PADconfigure)(void); +typedef void (CALLBACK* PADabout)(void); +typedef long (CALLBACK* PADinit)(long); +typedef long (CALLBACK* PADshutdown)(void); +typedef long (CALLBACK* PADtest)(void); +typedef long (CALLBACK* PADclose)(void); +typedef long (CALLBACK* PADquery)(void); +typedef long (CALLBACK* PADreadPort1)(PadDataS*); +typedef long (CALLBACK* PADreadPort2)(PadDataS*); +typedef long (CALLBACK* PADkeypressed)(void); +typedef unsigned char (CALLBACK* PADstartPoll)(int); +typedef unsigned char (CALLBACK* PADpoll)(unsigned char); +typedef void (CALLBACK* PADsetSensitive)(int); +typedef void (CALLBACK* PADregisterVibration)(void (CALLBACK *callback)(uint32_t, uint32_t)); +typedef void (CALLBACK* PADregisterCursor)(void (CALLBACK *callback)(int, int, int)); + +// PAD function pointers +extern PADconfigure PAD1_configure; +extern PADabout PAD1_about; +extern PADinit PAD1_init; +extern PADshutdown PAD1_shutdown; +extern PADtest PAD1_test; +extern PADopen PAD1_open; +extern PADclose PAD1_close; +extern PADquery PAD1_query; +extern PADreadPort1 PAD1_readPort1; +extern PADkeypressed PAD1_keypressed; +extern PADstartPoll PAD1_startPoll; +extern PADpoll PAD1_poll; +extern PADsetSensitive PAD1_setSensitive; +extern PADregisterVibration PAD1_registerVibration; +extern PADregisterCursor PAD1_registerCursor; +extern PADconfigure PAD2_configure; +extern PADabout PAD2_about; +extern PADinit PAD2_init; +extern PADshutdown PAD2_shutdown; +extern PADtest PAD2_test; +extern PADopen PAD2_open; +extern PADclose PAD2_close; +extern PADquery PAD2_query; +extern PADreadPort2 PAD2_readPort2; +extern PADkeypressed PAD2_keypressed; +extern PADstartPoll PAD2_startPoll; +extern PADpoll PAD2_poll; +extern PADsetSensitive PAD2_setSensitive; +extern PADregisterVibration PAD2_registerVibration; +extern PADregisterCursor PAD2_registerCursor; + +// NET Functions +typedef long (CALLBACK* NETinit)(void); +typedef long (CALLBACK* NETshutdown)(void); +typedef long (CALLBACK* NETclose)(void); +typedef long (CALLBACK* NETconfigure)(void); +typedef long (CALLBACK* NETtest)(void); +typedef void (CALLBACK* NETabout)(void); +typedef void (CALLBACK* NETpause)(void); +typedef void (CALLBACK* NETresume)(void); +typedef long (CALLBACK* NETqueryPlayer)(void); +typedef long (CALLBACK* NETsendData)(void *, int, int); +typedef long (CALLBACK* NETrecvData)(void *, int, int); +typedef long (CALLBACK* NETsendPadData)(void *, int); +typedef long (CALLBACK* NETrecvPadData)(void *, int); + +typedef struct { + char EmuName[32]; + char CdromID[9]; // ie. 'SCPH12345', no \0 trailing character + char CdromLabel[11]; + void *psxMem; + GPUshowScreenPic GPU_showScreenPic; + GPUdisplayText GPU_displayText; + PADsetSensitive PAD_setSensitive; + char GPUpath[256]; // paths must be absolute + char SPUpath[256]; + char CDRpath[256]; + char MCD1path[256]; + char MCD2path[256]; + char BIOSpath[256]; // 'HLE' for internal bios + char Unused[1024]; +} netInfo; + +typedef long (CALLBACK* NETsetInfo)(netInfo *); +typedef long (CALLBACK* NETkeypressed)(int); + +// NET function pointers +extern NETinit NET_init; +extern NETshutdown NET_shutdown; +extern NETopen NET_open; +extern NETclose NET_close; +extern NETtest NET_test; +extern NETconfigure NET_configure; +extern NETabout NET_about; +extern NETpause NET_pause; +extern NETresume NET_resume; +extern NETqueryPlayer NET_queryPlayer; +extern NETsendData NET_sendData; +extern NETrecvData NET_recvData; +extern NETsendPadData NET_sendPadData; +extern NETrecvPadData NET_recvPadData; +extern NETsetInfo NET_setInfo; +extern NETkeypressed NET_keypressed; + +#ifdef ENABLE_SIO1API + +// SIO1 Functions (link cable) +typedef long (CALLBACK* SIO1init)(void); +typedef long (CALLBACK* SIO1shutdown)(void); +typedef long (CALLBACK* SIO1close)(void); +typedef long (CALLBACK* SIO1configure)(void); +typedef long (CALLBACK* SIO1test)(void); +typedef void (CALLBACK* SIO1about)(void); +typedef void (CALLBACK* SIO1pause)(void); +typedef void (CALLBACK* SIO1resume)(void); +typedef long (CALLBACK* SIO1keypressed)(int); +typedef void (CALLBACK* SIO1writeData8)(unsigned char); +typedef void (CALLBACK* SIO1writeData16)(unsigned short); +typedef void (CALLBACK* SIO1writeData32)(unsigned long); +typedef void (CALLBACK* SIO1writeStat16)(unsigned short); +typedef void (CALLBACK* SIO1writeStat32)(unsigned long); +typedef void (CALLBACK* SIO1writeMode16)(unsigned short); +typedef void (CALLBACK* SIO1writeMode32)(unsigned long); +typedef void (CALLBACK* SIO1writeCtrl16)(unsigned short); +typedef void (CALLBACK* SIO1writeCtrl32)(unsigned long); +typedef void (CALLBACK* SIO1writeBaud16)(unsigned short); +typedef void (CALLBACK* SIO1writeBaud32)(unsigned long); +typedef unsigned char (CALLBACK* SIO1readData8)(void); +typedef unsigned short (CALLBACK* SIO1readData16)(void); +typedef unsigned long (CALLBACK* SIO1readData32)(void); +typedef unsigned short (CALLBACK* SIO1readStat16)(void); +typedef unsigned long (CALLBACK* SIO1readStat32)(void); +typedef unsigned short (CALLBACK* SIO1readMode16)(void); +typedef unsigned long (CALLBACK* SIO1readMode32)(void); +typedef unsigned short (CALLBACK* SIO1readCtrl16)(void); +typedef unsigned long (CALLBACK* SIO1readCtrl32)(void); +typedef unsigned short (CALLBACK* SIO1readBaud16)(void); +typedef unsigned long (CALLBACK* SIO1readBaud32)(void); +typedef void (CALLBACK* SIO1registerCallback)(void (CALLBACK *callback)(void)); + +// SIO1 function pointers +extern SIO1init SIO1_init; +extern SIO1shutdown SIO1_shutdown; +extern SIO1open SIO1_open; +extern SIO1close SIO1_close; +extern SIO1test SIO1_test; +extern SIO1configure SIO1_configure; +extern SIO1about SIO1_about; +extern SIO1pause SIO1_pause; +extern SIO1resume SIO1_resume; +extern SIO1keypressed SIO1_keypressed; +extern SIO1writeData8 SIO1_writeData8; +extern SIO1writeData16 SIO1_writeData16; +extern SIO1writeData32 SIO1_writeData32; +extern SIO1writeStat16 SIO1_writeStat16; +extern SIO1writeStat32 SIO1_writeStat32; +extern SIO1writeMode16 SIO1_writeMode16; +extern SIO1writeMode32 SIO1_writeMode32; +extern SIO1writeCtrl16 SIO1_writeCtrl16; +extern SIO1writeCtrl32 SIO1_writeCtrl32; +extern SIO1writeBaud16 SIO1_writeBaud16; +extern SIO1writeBaud32 SIO1_writeBaud32; +extern SIO1readData8 SIO1_readData8; +extern SIO1readData16 SIO1_readData16; +extern SIO1readData32 SIO1_readData32; +extern SIO1readStat16 SIO1_readStat16; +extern SIO1readStat32 SIO1_readStat32; +extern SIO1readMode16 SIO1_readMode16; +extern SIO1readMode32 SIO1_readMode32; +extern SIO1readCtrl16 SIO1_readCtrl16; +extern SIO1readCtrl32 SIO1_readCtrl32; +extern SIO1readBaud16 SIO1_readBaud16; +extern SIO1readBaud32 SIO1_readBaud32; +extern SIO1registerCallback SIO1_registerCallback; + +#endif + +void CALLBACK clearDynarec(void); + +void SetIsoFile(const char *filename); +const char *GetIsoFile(void); +boolean UsingIso(void); +void SetCdOpenCaseTime(s64 time); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/ppc/pR3000A.c b/libpcsxcore/ppc/pR3000A.c index 4b890880..d2847f38 100644..100755 --- a/libpcsxcore/ppc/pR3000A.c +++ b/libpcsxcore/ppc/pR3000A.c @@ -1,3543 +1,3543 @@ -/* Pcsx - Pc Psx Emulator
- * Copyright (C) 1999-2003 Pcsx 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#if defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__) || defined (__powerpc64__) || defined (__POWERPC__)
-
-#ifdef _MSC_VER_
-#pragma warning(disable:4244)
-#pragma warning(disable:4761)
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-#include "../psxcommon.h"
-#include "ppc.h"
-#include "reguse.h"
-#include "../r3000a.h"
-#include "../psxhle.h"
-
-//#define NO_CONSTANT
-
-u32 *psxRecLUT;
-
-#undef _Op_
-#define _Op_ _fOp_(psxRegs.code)
-#undef _Funct_
-#define _Funct_ _fFunct_(psxRegs.code)
-#undef _Rd_
-#define _Rd_ _fRd_(psxRegs.code)
-#undef _Rt_
-#define _Rt_ _fRt_(psxRegs.code)
-#undef _Rs_
-#define _Rs_ _fRs_(psxRegs.code)
-#undef _Sa_
-#define _Sa_ _fSa_(psxRegs.code)
-#undef _Im_
-#define _Im_ _fIm_(psxRegs.code)
-#undef _Target_
-#define _Target_ _fTarget_(psxRegs.code)
-
-#undef _Imm_
-#define _Imm_ _fImm_(psxRegs.code)
-#undef _ImmU_
-#define _ImmU_ _fImmU_(psxRegs.code)
-
-#undef PC_REC
-#undef PC_REC8
-#undef PC_REC16
-#undef PC_REC32
-#define PC_REC(x) (psxRecLUT[x >> 16] + (x & 0xffff))
-#define PC_REC8(x) (*(u8 *)PC_REC(x))
-#define PC_REC16(x) (*(u16*)PC_REC(x))
-#define PC_REC32(x) (*(u32*)PC_REC(x))
-
-#define OFFSET(X,Y) ((u32)(Y)-(u32)(X))
-
-#define RECMEM_SIZE (12*1024*1024)
-
-static char *recMem; /* the recompiled blocks will be here */
-static char *recRAM; /* and the ptr to the blocks here */
-static char *recROM; /* and here */
-
-static u32 pc; /* recompiler pc */
-static u32 pcold; /* recompiler oldpc */
-static int count; /* recompiler intruction count */
-static int branch; /* set for branch */
-static u32 target; /* branch target */
-static u32 resp;
-
-u32 cop2readypc = 0;
-u32 idlecyclecount = 0;
-
-#define NUM_REGISTERS 34
-typedef struct {
- int state;
- u32 k;
- int reg;
-} iRegisters;
-
-static iRegisters iRegs[34];
-
-#define ST_UNK 0x00
-#define ST_CONST 0x01
-#define ST_MAPPED 0x02
-
-#ifdef NO_CONSTANT
-#define IsConst(reg) 0
-#else
-#define IsConst(reg) (iRegs[reg].state & ST_CONST)
-#endif
-#define IsMapped(reg) (iRegs[reg].state & ST_MAPPED)
-
-static void (*recBSC[64])();
-static void (*recSPC[64])();
-static void (*recREG[32])();
-static void (*recCP0[32])();
-static void (*recCP2[64])();
-static void (*recCP2BSC[32])();
-
-#define REG_LO 32
-#define REG_HI 33
-
-// Hardware register usage
-#define HWUSAGE_NONE 0x00
-
-#define HWUSAGE_READ 0x01
-#define HWUSAGE_WRITE 0x02
-#define HWUSAGE_CONST 0x04
-#define HWUSAGE_ARG 0x08 /* used as an argument for a function call */
-
-#define HWUSAGE_RESERVED 0x10 /* won't get flushed when flushing all regs */
-#define HWUSAGE_SPECIAL 0x20 /* special purpose register */
-#define HWUSAGE_HARDWIRED 0x40 /* specific hardware register mapping that is never disposed */
-#define HWUSAGE_INITED 0x80
-#define HWUSAGE_PSXREG 0x100
-
-// Remember to invalidate the special registers if they are modified by compiler
-enum {
- ARG1 = 3,
- ARG2 = 4,
- ARG3 = 5,
- PSXREGS, // ptr
- PSXMEM, // ptr
- CYCLECOUNT, // ptr
- PSXPC, // ptr
- TARGETPTR, // ptr
- TARGET, // ptr
- RETVAL,
- REG_RZERO,
- REG_WZERO
-};
-
-typedef struct {
- int code;
- u32 k;
- int usage;
- int lastUsed;
-
- void (*flush)(int hwreg);
- int private;
-} HWRegister;
-static HWRegister HWRegisters[NUM_HW_REGISTERS];
-static int HWRegUseCount;
-static int DstCPUReg;
-static int UniqueRegAlloc;
-
-static int GetFreeHWReg();
-static void InvalidateCPURegs();
-static void DisposeHWReg(int index);
-static void FlushHWReg(int index);
-static void FlushAllHWReg();
-static void MapPsxReg32(int reg);
-static void FlushPsxReg32(int hwreg);
-static int UpdateHWRegUsage(int hwreg, int usage);
-static int GetHWReg32(int reg);
-static int PutHWReg32(int reg);
-static int GetSpecialIndexFromHWRegs(int which);
-static int GetHWRegFromCPUReg(int cpureg);
-static int MapRegSpecial(int which);
-static void FlushRegSpecial(int hwreg);
-static int GetHWRegSpecial(int which);
-static int PutHWRegSpecial(int which);
-static void recRecompile();
-static void recError();
-
-#pragma mark --- Generic register mapping ---
-
-static int GetFreeHWReg()
-{
- int i, least, index;
-
- if (DstCPUReg != -1) {
- index = GetHWRegFromCPUReg(DstCPUReg);
- DstCPUReg = -1;
- } else {
- // LRU algorith with a twist ;)
- for (i=0; i<NUM_HW_REGISTERS; i++) {
- if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
- break;
- }
- }
-
- least = HWRegisters[i].lastUsed; index = i;
- for (; i<NUM_HW_REGISTERS; i++) {
- if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
- if (HWRegisters[i].usage == HWUSAGE_NONE && HWRegisters[i].code >= 13) {
- index = i;
- break;
- }
- else if (HWRegisters[i].lastUsed < least) {
- least = HWRegisters[i].lastUsed;
- index = i;
- }
- }
- }
-
- // Cycle the registers
- if (HWRegisters[index].usage == HWUSAGE_NONE) {
- for (; i<NUM_HW_REGISTERS; i++) {
- if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
- if (HWRegisters[i].usage == HWUSAGE_NONE &&
- HWRegisters[i].code >= 13 &&
- HWRegisters[i].lastUsed < least) {
- least = HWRegisters[i].lastUsed;
- index = i;
- break;
- }
- }
- }
- }
- }
-
-/* if (HWRegisters[index].code < 13 && HWRegisters[index].code > 3) {
- SysPrintf("Allocating volatile register %i\n", HWRegisters[index].code);
- }
- if (HWRegisters[index].usage != HWUSAGE_NONE) {
- SysPrintf("RegUse too big. Flushing %i\n", HWRegisters[index].code);
- }*/
- if (HWRegisters[index].usage & (HWUSAGE_RESERVED | HWUSAGE_HARDWIRED)) {
- if (HWRegisters[index].usage & HWUSAGE_RESERVED) {
- SysPrintf("Error! Trying to map a new register to a reserved register (r%i)",
- HWRegisters[index].code);
- }
- if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) {
- SysPrintf("Error! Trying to map a new register to a hardwired register (r%i)",
- HWRegisters[index].code);
- }
- }
-
- if (HWRegisters[index].lastUsed != 0) {
- UniqueRegAlloc = 0;
- }
-
- // Make sure the register is really flushed!
- FlushHWReg(index);
- HWRegisters[index].usage = HWUSAGE_NONE;
- HWRegisters[index].flush = NULL;
-
- return index;
-}
-
-static void FlushHWReg(int index)
-{
- if (index < 0) return;
- if (HWRegisters[index].usage == HWUSAGE_NONE) return;
-
- if (HWRegisters[index].flush) {
- HWRegisters[index].usage |= HWUSAGE_RESERVED;
- HWRegisters[index].flush(index);
- HWRegisters[index].flush = NULL;
- }
-
- if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) {
- HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE);
- } else {
- HWRegisters[index].usage = HWUSAGE_NONE;
- }
-}
-
-// get rid of a mapped register without flushing the contents to the memory
-static void DisposeHWReg(int index)
-{
- if (index < 0) return;
- if (HWRegisters[index].usage == HWUSAGE_NONE) return;
-
- HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE);
- if (HWRegisters[index].usage == HWUSAGE_NONE) {
- SysPrintf("Error! not correctly disposing register (r%i)", HWRegisters[index].code);
- }
-
- FlushHWReg(index);
-}
-
-// operated on cpu registers
-__inline static void FlushCPURegRange(int start, int end)
-{
- int i;
-
- if (end <= 0) end = 31;
- if (start <= 0) start = 0;
-
- for (i=0; i<NUM_HW_REGISTERS; i++) {
- if (HWRegisters[i].code >= start && HWRegisters[i].code <= end)
- if (HWRegisters[i].flush)
- FlushHWReg(i);
- }
-
- for (i=0; i<NUM_HW_REGISTERS; i++) {
- if (HWRegisters[i].code >= start && HWRegisters[i].code <= end)
- FlushHWReg(i);
- }
-}
-
-static void FlushAllHWReg()
-{
- FlushCPURegRange(0,31);
-}
-
-static void InvalidateCPURegs()
-{
- FlushCPURegRange(0,12);
-}
-
-#pragma mark --- Mapping utility functions ---
-
-static void MoveHWRegToCPUReg(int cpureg, int hwreg)
-{
- int dstreg;
-
- if (HWRegisters[hwreg].code == cpureg)
- return;
-
- dstreg = GetHWRegFromCPUReg(cpureg);
-
- HWRegisters[dstreg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG);
- if (HWRegisters[hwreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) {
- FlushHWReg(dstreg);
- MR(HWRegisters[dstreg].code, HWRegisters[hwreg].code);
- } else {
- if (HWRegisters[dstreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) {
- MR(HWRegisters[hwreg].code, HWRegisters[dstreg].code);
- }
- else if (HWRegisters[dstreg].usage != HWUSAGE_NONE) {
- FlushHWReg(dstreg);
- }
- }
-
- HWRegisters[dstreg].code = HWRegisters[hwreg].code;
- HWRegisters[hwreg].code = cpureg;
-}
-
-static int UpdateHWRegUsage(int hwreg, int usage)
-{
- HWRegisters[hwreg].lastUsed = ++HWRegUseCount;
- if (usage & HWUSAGE_WRITE) {
- HWRegisters[hwreg].usage &= ~HWUSAGE_CONST;
- }
- if (!(usage & HWUSAGE_INITED)) {
- HWRegisters[hwreg].usage &= ~HWUSAGE_INITED;
- }
- HWRegisters[hwreg].usage |= usage;
-
- return HWRegisters[hwreg].code;
-}
-
-static int GetHWRegFromCPUReg(int cpureg)
-{
- int i;
- for (i=0; i<NUM_HW_REGISTERS; i++) {
- if (HWRegisters[i].code == cpureg) {
- return i;
- }
- }
-
- SysPrintf("Error! Register location failure (r%i)", cpureg);
- return 0;
-}
-
-// this function operates on cpu registers
-void SetDstCPUReg(int cpureg)
-{
- DstCPUReg = cpureg;
-}
-
-static void ReserveArgs(int args)
-{
- int index, i;
-
- for (i=0; i<args; i++) {
- index = GetHWRegFromCPUReg(3+i);
- HWRegisters[index].usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG;
- }
-}
-
-static void ReleaseArgs()
-{
- int i;
-
- for (i=0; i<NUM_HW_REGISTERS; i++) {
- if (HWRegisters[i].usage & HWUSAGE_ARG) {
- //HWRegisters[i].usage = HWUSAGE_NONE;
- //HWRegisters[i].flush = NULL;
- HWRegisters[i].usage &= ~(HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG);
- FlushHWReg(i);
- }
- }
-}
-
-#pragma mark --- Psx register mapping ---
-
-static void MapPsxReg32(int reg)
-{
- int hwreg = GetFreeHWReg();
- HWRegisters[hwreg].flush = FlushPsxReg32;
- HWRegisters[hwreg].private = reg;
-
- if (iRegs[reg].reg != -1) {
- SysPrintf("error: double mapped psx register");
- }
-
- iRegs[reg].reg = hwreg;
- iRegs[reg].state |= ST_MAPPED;
-}
-
-static void FlushPsxReg32(int hwreg)
-{
- int reg = HWRegisters[hwreg].private;
-
- if (iRegs[reg].reg == -1) {
- SysPrintf("error: flushing unmapped psx register");
- }
-
- if (HWRegisters[hwreg].usage & HWUSAGE_WRITE) {
- if (branch) {
- /*int reguse = nextPsxRegUse(pc-8, reg);
- if (reguse == REGUSE_NONE || (reguse & REGUSE_READ))*/ {
- STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
- }
- } else {
- int reguse = nextPsxRegUse(pc-4, reg);
- if (reguse == REGUSE_NONE || (reguse & REGUSE_READ)) {
- STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
- }
- }
- }
-
- iRegs[reg].reg = -1;
- iRegs[reg].state = ST_UNK;
-}
-
-static int GetHWReg32(int reg)
-{
- int usage = HWUSAGE_PSXREG | HWUSAGE_READ;
-
- if (reg == 0) {
- return GetHWRegSpecial(REG_RZERO);
- }
- if (!IsMapped(reg)) {
- usage |= HWUSAGE_INITED;
- MapPsxReg32(reg);
-
- HWRegisters[iRegs[reg].reg].usage |= HWUSAGE_RESERVED;
- if (IsConst(reg)) {
- LIW(HWRegisters[iRegs[reg].reg].code, iRegs[reg].k);
- usage |= HWUSAGE_WRITE | HWUSAGE_CONST;
- //iRegs[reg].state &= ~ST_CONST;
- }
- else {
- LWZ(HWRegisters[iRegs[reg].reg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
- }
- HWRegisters[iRegs[reg].reg].usage &= ~HWUSAGE_RESERVED;
- }
- else if (DstCPUReg != -1) {
- int dst = DstCPUReg;
- DstCPUReg = -1;
-
- if (HWRegisters[iRegs[reg].reg].code < 13) {
- MoveHWRegToCPUReg(dst, iRegs[reg].reg);
- } else {
- MR(DstCPUReg, HWRegisters[iRegs[reg].reg].code);
- }
- }
-
- DstCPUReg = -1;
-
- return UpdateHWRegUsage(iRegs[reg].reg, usage);
-}
-
-static int PutHWReg32(int reg)
-{
- int usage = HWUSAGE_PSXREG | HWUSAGE_WRITE;
- if (reg == 0) {
- return PutHWRegSpecial(REG_WZERO);
- }
-
- if (DstCPUReg != -1 && IsMapped(reg)) {
- if (HWRegisters[iRegs[reg].reg].code != DstCPUReg) {
- int tmp = DstCPUReg;
- DstCPUReg = -1;
- DisposeHWReg(iRegs[reg].reg);
- DstCPUReg = tmp;
- }
- }
- if (!IsMapped(reg)) {
- usage |= HWUSAGE_INITED;
- MapPsxReg32(reg);
- }
-
- DstCPUReg = -1;
- iRegs[reg].state &= ~ST_CONST;
-
- return UpdateHWRegUsage(iRegs[reg].reg, usage);
-}
-
-#pragma mark --- Special register mapping ---
-
-static int GetSpecialIndexFromHWRegs(int which)
-{
- int i;
- for (i=0; i<NUM_HW_REGISTERS; i++) {
- if (HWRegisters[i].usage & HWUSAGE_SPECIAL) {
- if (HWRegisters[i].private == which) {
- return i;
- }
- }
- }
- return -1;
-}
-
-static int MapRegSpecial(int which)
-{
- int hwreg = GetFreeHWReg();
- HWRegisters[hwreg].flush = FlushRegSpecial;
- HWRegisters[hwreg].private = which;
-
- return hwreg;
-}
-
-static void FlushRegSpecial(int hwreg)
-{
- int which = HWRegisters[hwreg].private;
-
- if (!(HWRegisters[hwreg].usage & HWUSAGE_WRITE))
- return;
-
- switch (which) {
- case CYCLECOUNT:
- STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS));
- break;
- case PSXPC:
- STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS));
- break;
- case TARGET:
- STW(HWRegisters[hwreg].code, 0, GetHWRegSpecial(TARGETPTR));
- break;
- }
-}
-
-static int GetHWRegSpecial(int which)
-{
- int index = GetSpecialIndexFromHWRegs(which);
- int usage = HWUSAGE_READ | HWUSAGE_SPECIAL;
-
- if (index == -1) {
- usage |= HWUSAGE_INITED;
- index = MapRegSpecial(which);
-
- HWRegisters[index].usage |= HWUSAGE_RESERVED;
- switch (which) {
- case PSXREGS:
- case PSXMEM:
- SysPrintf("error! shouldn't be here!\n");
- //HWRegisters[index].flush = NULL;
- //LIW(HWRegisters[index].code, (u32)&psxRegs);
- break;
- case TARGETPTR:
- HWRegisters[index].flush = NULL;
- LIW(HWRegisters[index].code, (u32)&target);
- break;
- case REG_RZERO:
- HWRegisters[index].flush = NULL;
- LIW(HWRegisters[index].code, 0);
- break;
- case RETVAL:
- MoveHWRegToCPUReg(3, index);
- /*reg = GetHWRegFromCPUReg(3);
- HWRegisters[reg].code = HWRegisters[index].code;
- HWRegisters[index].code = 3;*/
- HWRegisters[index].flush = NULL;
-
- usage |= HWUSAGE_RESERVED;
- break;
-
- case CYCLECOUNT:
- LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS));
- break;
- case PSXPC:
- LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS));
- break;
- case TARGET:
- LWZ(HWRegisters[index].code, 0, GetHWRegSpecial(TARGETPTR));
- break;
- default:
- SysPrintf("Error: Unknown special register in GetHWRegSpecial()\n");
- break;
- }
- HWRegisters[index].usage &= ~HWUSAGE_RESERVED;
- }
- else if (DstCPUReg != -1) {
- int dst = DstCPUReg;
- DstCPUReg = -1;
-
- MoveHWRegToCPUReg(dst, index);
- }
-
- return UpdateHWRegUsage(index, usage);
-}
-
-static int PutHWRegSpecial(int which)
-{
- int index = GetSpecialIndexFromHWRegs(which);
- int usage = HWUSAGE_WRITE | HWUSAGE_SPECIAL;
-
- if (DstCPUReg != -1 && index != -1) {
- if (HWRegisters[index].code != DstCPUReg) {
- int tmp = DstCPUReg;
- DstCPUReg = -1;
- DisposeHWReg(index);
- DstCPUReg = tmp;
- }
- }
- switch (which) {
- case PSXREGS:
- case TARGETPTR:
- SysPrintf("Error: Read-only special register in PutHWRegSpecial()\n");
- case REG_WZERO:
- if (index >= 0) {
- if (HWRegisters[index].usage & HWUSAGE_WRITE)
- break;
- }
- index = MapRegSpecial(which);
- HWRegisters[index].flush = NULL;
- break;
- default:
- if (index == -1) {
- usage |= HWUSAGE_INITED;
- index = MapRegSpecial(which);
-
- HWRegisters[index].usage |= HWUSAGE_RESERVED;
- switch (which) {
- case ARG1:
- case ARG2:
- case ARG3:
- MoveHWRegToCPUReg(3+(which-ARG1), index);
- /*reg = GetHWRegFromCPUReg(3+(which-ARG1));
-
- if (HWRegisters[reg].usage != HWUSAGE_NONE) {
- HWRegisters[reg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG);
- if (HWRegisters[reg].flush != NULL && HWRegisters[reg].usage & (HWUSAGE_WRITE | HWUSAGE_READ)) {
- MR(HWRegisters[index].code, HWRegisters[reg].code);
- } else {
- FlushHWReg(reg);
- }
- }
- HWRegisters[reg].code = HWRegisters[index].code;
- if (!(HWRegisters[index].code >= 3 && HWRegisters[index].code <=31))
- SysPrintf("Error! Register allocation");
- HWRegisters[index].code = 3+(which-ARG1);*/
- HWRegisters[index].flush = NULL;
-
- usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG;
- break;
- }
- }
- HWRegisters[index].usage &= ~HWUSAGE_RESERVED;
- break;
- }
-
- DstCPUReg = -1;
-
- return UpdateHWRegUsage(index, usage);
-}
-
-#pragma mark --- ---
-
-static void MapConst(int reg, u32 _const) {
- if (reg == 0)
- return;
- if (IsConst(reg) && iRegs[reg].k == _const)
- return;
-
- DisposeHWReg(iRegs[reg].reg);
- iRegs[reg].k = _const;
- iRegs[reg].state = ST_CONST;
-}
-
-static void MapCopy(int dst, int src)
-{
- // do it the lazy way for now
- MR(PutHWReg32(dst), GetHWReg32(src));
-}
-
-static void iFlushReg(u32 nextpc, int reg) {
- if (!IsMapped(reg) && IsConst(reg)) {
- GetHWReg32(reg);
- }
- if (IsMapped(reg)) {
- if (nextpc) {
- int use = nextPsxRegUse(nextpc, reg);
- if ((use & REGUSE_RW) == REGUSE_WRITE) {
- DisposeHWReg(iRegs[reg].reg);
- } else {
- FlushHWReg(iRegs[reg].reg);
- }
- } else {
- FlushHWReg(iRegs[reg].reg);
- }
- }
-}
-
-static void iFlushRegs(u32 nextpc) {
- int i;
-
- for (i=1; i<NUM_REGISTERS; i++) {
- iFlushReg(nextpc, i);
- }
-}
-
-static void Return()
-{
- iFlushRegs(0);
- FlushAllHWReg();
- if (((u32)returnPC & 0x1fffffc) == (u32)returnPC) {
- BA((u32)returnPC);
- }
- else {
- LIW(0, (u32)returnPC);
- MTLR(0);
- BLR();
- }
-}
-
-static void iRet() {
- /* store cycle */
- count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
- Return();
-}
-
-static int iLoadTest() {
- u32 tmp;
-
- // check for load delay
- tmp = psxRegs.code >> 26;
- switch (tmp) {
- case 0x10: // COP0
- switch (_Rs_) {
- case 0x00: // MFC0
- case 0x02: // CFC0
- return 1;
- }
- break;
- case 0x12: // COP2
- switch (_Funct_) {
- case 0x00:
- switch (_Rs_) {
- case 0x00: // MFC2
- case 0x02: // CFC2
- return 1;
- }
- break;
- }
- break;
- case 0x32: // LWC2
- return 1;
- default:
- if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
- return 1;
- }
- break;
- }
- return 0;
-}
-
-/* set a pending branch */
-static void SetBranch() {
- int treg;
- branch = 1;
- psxRegs.code = PSXMu32(pc);
- pc+=4;
-
- if (iLoadTest() == 1) {
- iFlushRegs(0);
- LIW(0, psxRegs.code);
- STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
- /* store cycle */
- count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
-
- treg = GetHWRegSpecial(TARGET);
- MR(PutHWRegSpecial(ARG2), treg);
- DisposeHWReg(GetHWRegFromCPUReg(treg));
- LIW(PutHWRegSpecial(ARG1), _Rt_);
- LIW(GetHWRegSpecial(PSXPC), pc);
- FlushAllHWReg();
- CALLFunc((u32)psxDelayTest);
-
- Return();
- return;
- }
-
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs(0);
- treg = GetHWRegSpecial(TARGET);
- MR(PutHWRegSpecial(PSXPC), GetHWRegSpecial(TARGET)); // FIXME: this line should not be needed
- DisposeHWReg(GetHWRegFromCPUReg(treg));
- FlushAllHWReg();
-
- count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
- FlushAllHWReg();
- CALLFunc((u32)psxBranchTest);
-
- // TODO: don't return if target is compiled
- Return();
-}
-
-static void iJump(u32 branchPC) {
- u32 *b1, *b2;
- branch = 1;
- psxRegs.code = PSXMu32(pc);
- pc+=4;
-
- if (iLoadTest() == 1) {
- iFlushRegs(0);
- LIW(0, psxRegs.code);
- STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
- /* store cycle */
- count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
-
- LIW(PutHWRegSpecial(ARG2), branchPC);
- LIW(PutHWRegSpecial(ARG1), _Rt_);
- LIW(GetHWRegSpecial(PSXPC), pc);
- FlushAllHWReg();
- CALLFunc((u32)psxDelayTest);
-
- Return();
- return;
- }
-
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs(branchPC);
- LIW(PutHWRegSpecial(PSXPC), branchPC);
- FlushAllHWReg();
-
- count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
- //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) {
- // LIW(PutHWRegSpecial(CYCLECOUNT), 0);
- //} else {
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
- //}
- FlushAllHWReg();
- CALLFunc((u32)psxBranchTest);
-
- if (!Config.HLE && Config.PsxOut &&
- ((branchPC & 0x1fffff) == 0xa0 ||
- (branchPC & 0x1fffff) == 0xb0 ||
- (branchPC & 0x1fffff) == 0xc0))
- CALLFunc((u32)psxJumpTest);
-
- // always return for now...
- //Return();
-
- // maybe just happened an interruption, check so
- LIW(0, branchPC);
- CMPLW(GetHWRegSpecial(PSXPC), 0);
- BNE_L(b1);
-
- LIW(3, PC_REC(branchPC));
- LWZ(3, 0, 3);
- CMPLWI(3, 0);
- BNE_L(b2);
-
- B_DST(b1);
- Return();
-
- // next bit is already compiled - jump right to it
- B_DST(b2);
- MTCTR(3);
- BCTR();
-}
-
-static void iBranch(u32 branchPC, int savectx) {
- HWRegister HWRegistersS[NUM_HW_REGISTERS];
- iRegisters iRegsS[NUM_REGISTERS];
- int HWRegUseCountS = 0;
- u32 respold=0;
- u32 *b1, *b2;
-
- if (savectx) {
- respold = resp;
- memcpy(iRegsS, iRegs, sizeof(iRegs));
- memcpy(HWRegistersS, HWRegisters, sizeof(HWRegisters));
- HWRegUseCountS = HWRegUseCount;
- }
-
- branch = 1;
- psxRegs.code = PSXMu32(pc);
-
- // the delay test is only made when the branch is taken
- // savectx == 0 will mean that :)
- if (savectx == 0 && iLoadTest() == 1) {
- iFlushRegs(0);
- LIW(0, psxRegs.code);
- STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
- /* store cycle */
- count = (idlecyclecount + ((pc+4) - pcold) / 4) * BIAS;
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
-
- LIW(PutHWRegSpecial(ARG2), branchPC);
- LIW(PutHWRegSpecial(ARG1), _Rt_);
- LIW(GetHWRegSpecial(PSXPC), pc);
- FlushAllHWReg();
- CALLFunc((u32)psxDelayTest);
-
- Return();
- return;
- }
-
- pc+= 4;
- recBSC[psxRegs.code>>26]();
-
- iFlushRegs(branchPC);
- LIW(PutHWRegSpecial(PSXPC), branchPC);
- FlushAllHWReg();
-
- /* store cycle */
- count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
- //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) {
- // LIW(PutHWRegSpecial(CYCLECOUNT), 0);
- //} else {
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
- //}
- FlushAllHWReg();
- CALLFunc((u32)psxBranchTest);
-
- // always return for now...
- //Return();
-
- LIW(0, branchPC);
- CMPLW(GetHWRegSpecial(PSXPC), 0);
- BNE_L(b1);
-
- LIW(3, PC_REC(branchPC));
- LWZ(3, 0, 3);
- CMPLWI(3, 0);
- BNE_L(b2);
-
- B_DST(b1);
- Return();
-
- B_DST(b2);
- MTCTR(3);
- BCTR();
-
- // maybe just happened an interruption, check so
-/* CMP32ItoM((u32)&psxRegs.pc, branchPC);
- j8Ptr[1] = JE8(0);
- RET();
-
- x86SetJ8(j8Ptr[1]);
- MOV32MtoR(EAX, PC_REC(branchPC));
- TEST32RtoR(EAX, EAX);
- j8Ptr[2] = JNE8(0);
- RET();
-
- x86SetJ8(j8Ptr[2]);
- JMP32R(EAX);*/
-
- pc-= 4;
- if (savectx) {
- resp = respold;
- memcpy(iRegs, iRegsS, sizeof(iRegs));
- memcpy(HWRegisters, HWRegistersS, sizeof(HWRegisters));
- HWRegUseCount = HWRegUseCountS;
- }
-}
-
-
-static void iDumpRegs() {
- int i, j;
-
- printf("%lx %lx\n", psxRegs.pc, psxRegs.cycle);
- for (i=0; i<4; i++) {
- for (j=0; j<8; j++)
- printf("%lx ", psxRegs.GPR.r[j*i]);
- printf("\n");
- }
-}
-
-void iDumpBlock(char *ptr) {
-/* FILE *f;
- u32 i;
-
- SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxCurrentCycle);
-
- for (i = psxRegs.pc; i < pc; i+=4)
- SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
-
- fflush(stdout);
- f = fopen("dump1", "w");
- fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f);
- fclose(f);
- system("ndisasmw -u dump1");
- fflush(stdout);*/
-}
-
-#define REC_FUNC(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(0); \
- LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
- STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
- LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
- FlushAllHWReg(); \
- CALLFunc((u32)psx##f); \
-/* branch = 2; */\
-}
-
-#define REC_SYS(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(0); \
- LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
- STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
- LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
- FlushAllHWReg(); \
- CALLFunc((u32)psx##f); \
- branch = 2; \
- iRet(); \
-}
-
-#define REC_BRANCH(f) \
-void psx##f(); \
-static void rec##f() { \
- iFlushRegs(0); \
- LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
- STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
- LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
- FlushAllHWReg(); \
- CALLFunc((u32)psx##f); \
- branch = 2; \
- iRet(); \
-}
-
-static void freeMem(int all)
-{
- if (recMem) free(recMem);
- if (recRAM) free(recRAM);
- if (recROM) free(recROM);
- recMem = recRAM = recROM = 0;
-
- if (all && psxRecLUT) {
- free(psxRecLUT); psxRecLUT = NULL;
- }
-}
-
-static int allocMem() {
- int i;
-
- freeMem(0);
-
- if (psxRecLUT==NULL)
- psxRecLUT = (u32*) malloc(0x010000 * 4);
-
- recMem = (char*) malloc(RECMEM_SIZE);
- //recMem = mmap(NULL, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
- recRAM = (char*) malloc(0x200000);
- recROM = (char*) malloc(0x080000);
- if (recRAM == NULL || recROM == NULL || recMem == NULL/*(void *)-1*/ || psxRecLUT == NULL) {
- freeMem(1);
- SysMessage("Error allocating memory"); return -1;
- }
-
- for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16];
- memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * 4);
- memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * 4);
-
- for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16];
-
- return 0;
-}
-
-static int recInit() {
- return allocMem();
-}
-
-static void recReset() {
- memset(recRAM, 0, 0x200000);
- memset(recROM, 0, 0x080000);
-
- ppcInit();
- ppcSetPtr((u32 *)recMem);
-
- branch = 0;
- memset(iRegs, 0, sizeof(iRegs));
- iRegs[0].state = ST_CONST;
- iRegs[0].k = 0;
-}
-
-static void recShutdown() {
- freeMem(1);
- ppcShutdown();
-}
-
-static void recError() {
- SysReset();
- ClosePlugins();
- SysMessage("Unrecoverable error while running recompiler\n");
- SysRunGui();
-}
-
-__inline static void execute() {
- void (**recFunc)();
- char *p;
-
- p = (char*)PC_REC(psxRegs.pc);
- /*if (p != NULL)*/ recFunc = (void (**)()) (u32)p;
- /*else { recError(); return; }*/
-
- if (*recFunc == 0) {
- recRecompile();
- }
- recRun(*recFunc, (u32)&psxRegs, (u32)&psxM);
-}
-
-static void recExecute() {
- for (;;) execute();
-}
-
-static void recExecuteBlock() {
- execute();
-}
-
-static void recClear(u32 Addr, u32 Size) {
- memset((void*)PC_REC(Addr), 0, Size * 4);
-}
-
-static void recNULL() {
-// SysMessage("recUNK: %8.8x\n", psxRegs.code);
-}
-
-/*********************************************************
-* goes to opcodes tables... *
-* Format: table[something....] *
-*********************************************************/
-
-//REC_SYS(SPECIAL);
-static void recSPECIAL() {
- recSPC[_Funct_]();
-}
-
-static void recREGIMM() {
- recREG[_Rt_]();
-}
-
-static void recCOP0() {
- recCP0[_Rs_]();
-}
-
-//REC_SYS(COP2);
-static void recCOP2() {
- recCP2[_Funct_]();
-}
-
-static void recBASIC() {
- recCP2BSC[_Rs_]();
-}
-
-//end of Tables opcodes...
-
-#pragma mark - Arithmetic with immediate operand -
-/*********************************************************
-* Arithmetic with immediate operand *
-* Format: OP rt, rs, immediate *
-*********************************************************/
-
-#if 0
-/*REC_FUNC(ADDI);
-REC_FUNC(ADDIU);
-REC_FUNC(ANDI);
-REC_FUNC(ORI);
-REC_FUNC(XORI);
-REC_FUNC(SLTI);
-REC_FUNC(SLTIU);*/
-#else
-static void recADDIU() {
-// Rt = Rs + Im
- if (!_Rt_) return;
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
- } else {
- if (_Imm_ == 0) {
- MapCopy(_Rt_, _Rs_);
- } else {
- ADDI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _Imm_);
- }
- }
-}
-
-static void recADDI() {
-// Rt = Rs + Im
- recADDIU();
-}
-
-//REC_FUNC(SLTI);
-//REC_FUNC(SLTIU);
-//CR0: SIGN | POSITIVE | ZERO | SOVERFLOW | SOVERFLOW | OVERFLOW | CARRY
-static void recSLTI() {
-// Rt = Rs < Im (signed)
- if (!_Rt_) return;
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
- } else {
- if (_Imm_ == 0) {
- SRWI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), 31);
- } else {
- int reg;
- CMPWI(GetHWReg32(_Rs_), _Imm_);
- reg = PutHWReg32(_Rt_);
- LI(reg, 1);
- BLT(1);
- LI(reg, 0);
- }
- }
-}
-
-static void recSLTIU() {
-// Rt = Rs < Im (unsigned)
- if (!_Rt_) return;
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
- } else {
- int reg;
- CMPLWI(GetHWReg32(_Rs_), _Imm_);
- reg = PutHWReg32(_Rt_);
- LI(reg, 1);
- BLT(1);
- LI(reg, 0);
- }
-}
-
-static void recANDI() {
-// Rt = Rs And Im
- if (!_Rt_) return;
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
- } else {
- ANDI_(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
- }
-}
-
-static void recORI() {
-// Rt = Rs Or Im
- if (!_Rt_) return;
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
- } else {
- if (_Imm_ == 0) {
- MapCopy(_Rt_, _Rs_);
- } else {
- ORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
- }
- }
-}
-
-static void recXORI() {
-// Rt = Rs Xor Im
- if (!_Rt_) return;
-
- if (IsConst(_Rs_)) {
- MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
- } else {
- XORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
- }
-}
-#endif
-//end of * Arithmetic with immediate operand
-
-/*********************************************************
-* Load higher 16 bits of the first word in GPR with imm *
-* Format: OP rt, immediate *
-*********************************************************/
-//REC_FUNC(LUI);
-//#if 0*/
-static void recLUI() {
-// Rt = Imm << 16
- if (!_Rt_) return;
-
- MapConst(_Rt_, psxRegs.code << 16);
-}
-//#endif
-//End of Load Higher .....
-
-#pragma mark - Register arithmetic -
-/*********************************************************
-* Register arithmetic *
-* Format: OP rd, rs, rt *
-*********************************************************/
-
-#if 0
-/*REC_FUNC(ADD);
-REC_FUNC(ADDU);
-REC_FUNC(SUB);
-REC_FUNC(SUBU);
-REC_FUNC(AND);
-REC_FUNC(OR);
-REC_FUNC(XOR);
-REC_FUNC(NOR);
-REC_FUNC(SLT);
-REC_FUNC(SLTU);*/
-#else
-static void recADDU() {
-// Rd = Rs + Rt
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k);
- } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
- ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), (s16)iRegs[_Rs_].k);
- } else if ((iRegs[_Rs_].k & 0xffff) == 0) {
- ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k>>16);
- } else {
- ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
- ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), (s16)iRegs[_Rt_].k);
- } else if ((iRegs[_Rt_].k & 0xffff) == 0) {
- ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k>>16);
- } else {
- ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else {
- ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-}
-
-static void recADD() {
-// Rd = Rs + Rt
- recADDU();
-}
-
-static void recSUBU() {
-// Rd = Rs - Rt
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k);
- } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((s32)(s16)(-iRegs[_Rt_].k) == (s32)(-iRegs[_Rt_].k)) {
- ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), -iRegs[_Rt_].k);
- } else if (((-iRegs[_Rt_].k) & 0xffff) == 0) {
- ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rs_), (-iRegs[_Rt_].k)>>16);
- } else {
- SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else {
- SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-}
-
-static void recSUB() {
-// Rd = Rs - Rt
- recSUBU();
-}
-
-static void recAND() {
-// Rd = Rs And Rt
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k);
- } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- // TODO: implement shifted (ANDIS) versions of these
- if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
- ANDI_(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
- ANDI_(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
- } else {
- AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else {
- AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-}
-
-static void recOR() {
-// Rd = Rs Or Rt
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
- }
- else {
- if (_Rs_ == _Rt_) {
- MapCopy(_Rd_, _Rs_);
- }
- else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
- ORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
- ORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
- } else {
- OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else {
- OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
-}
-
-static void recXOR() {
-// Rd = Rs Xor Rt
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k);
- } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
- XORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
- XORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
- } else {
- XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else {
- XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-}
-
-static void recNOR() {
-// Rd = Rs Nor Rt
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k));
- } /*else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
- NORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
- NORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
- } else {
- NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- } */else {
- NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-}
-
-static void recSLT() {
-// Rd = Rs < Rt (signed)
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
- } else { // TODO: add immidiate cases
- int reg;
- CMPW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- reg = PutHWReg32(_Rd_);
- LI(reg, 1);
- BLT(1);
- LI(reg, 0);
- }
-}
-
-static void recSLTU() {
-// Rd = Rs < Rt (unsigned)
- if (!_Rd_) return;
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k);
- } else { // TODO: add immidiate cases
- SUBFC(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
- SUBFE(PutHWReg32(_Rd_), GetHWReg32(_Rd_), GetHWReg32(_Rd_));
- NEG(PutHWReg32(_Rd_), GetHWReg32(_Rd_));
- }
-}
-#endif
-//End of * Register arithmetic
-
-#pragma mark - mult/div & Register trap logic -
-/*********************************************************
-* Register mult/div & Register trap logic *
-* Format: OP rs, rt *
-*********************************************************/
-
-#if 0
-REC_FUNC(MULT);
-REC_FUNC(MULTU);
-REC_FUNC(DIV);
-REC_FUNC(DIVU);
-#else
-
-int DoShift(u32 k)
-{
- u32 i;
- for (i=0; i<30; i++) {
- if (k == (1ul << i))
- return i;
- }
- return -1;
-}
-
-//REC_FUNC(MULT);
-
-// FIXME: doesn't work in GT - wrong way marker
-static void recMULT() {
-// Lo/Hi = Rs * Rt (signed)
- s32 k; int r;
- int usehi, uselo;
-
- if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
- (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
- MapConst(REG_LO, 0);
- MapConst(REG_HI, 0);
- return;
- }
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- u64 res = (s64)((s64)(s32)iRegs[_Rs_].k * (s64)(s32)iRegs[_Rt_].k);
- MapConst(REG_LO, (res & 0xffffffff));
- MapConst(REG_HI, ((res >> 32) & 0xffffffff));
- return;
- }
-
- if (IsConst(_Rs_)) {
- k = (s32)iRegs[_Rs_].k;
- r = _Rt_;
- } else if (IsConst(_Rt_)) {
- k = (s32)iRegs[_Rt_].k;
- r = _Rs_;
- } else {
- r = -1;
- k = 0;
- }
-
- // FIXME: this should not be needed!!!
-// uselo = isPsxRegUsed(pc, REG_LO);
-// usehi = isPsxRegUsed(pc, REG_HI);
- uselo = 1; //isPsxRegUsed(pc, REG_LO);
- usehi = 1; //isPsxRegUsed(pc, REG_HI);
-
-
- if (r != -1) {
- int shift = DoShift(k);
- if (shift != -1) {
- if (uselo) {
- SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift)
- }
- if (usehi) {
- SRAWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift);
- }
- } else {
- //if ((s32)(s16)k == k) {
- // MULLWI(PutHWReg32(REG_LO), GetHWReg32(r), k);
- // MULHWI(PutHWReg32(REG_HI), GetHWReg32(r), k);
- //} else
- {
- if (uselo) {
- MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- if (usehi) {
- MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- }
- } else {
- if (uselo) {
- MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- if (usehi) {
- MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
-}
-
-static void recMULTU() {
-// Lo/Hi = Rs * Rt (unsigned)
- u32 k; int r;
- int usehi, uselo;
-
- if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
- (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
- MapConst(REG_LO, 0);
- MapConst(REG_HI, 0);
- return;
- }
-
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- u64 res = (u64)((u64)(u32)iRegs[_Rs_].k * (u64)(u32)iRegs[_Rt_].k);
- MapConst(REG_LO, (res & 0xffffffff));
- MapConst(REG_HI, ((res >> 32) & 0xffffffff));
- return;
- }
-
- if (IsConst(_Rs_)) {
- k = (s32)iRegs[_Rs_].k;
- r = _Rt_;
- } else if (IsConst(_Rt_)) {
- k = (s32)iRegs[_Rt_].k;
- r = _Rs_;
- } else {
- r = -1;
- k = 0;
- }
-
- uselo = isPsxRegUsed(pc, REG_LO);
- usehi = isPsxRegUsed(pc, REG_HI);
-
- if (r != -1) {
- int shift = DoShift(k);
- if (shift != -1) {
- if (uselo) {
- SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift);
- }
- if (usehi) {
- SRWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift);
- }
- } else {
- {
- if (uselo) {
- MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- if (usehi) {
- MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- }
- } else {
- if (uselo) {
- MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- if (usehi) {
- MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
-}
-
-static void recDIV() {
-// Lo/Hi = Rs / Rt (signed)
- int usehi;
-
- if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) {
- MapConst(REG_LO, 0);
- MapConst(REG_HI, 0);
- return;
- }
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(REG_LO, (s32)iRegs[_Rs_].k / (s32)iRegs[_Rt_].k);
- MapConst(REG_HI, (s32)iRegs[_Rs_].k % (s32)iRegs[_Rt_].k);
- return;
- }
-
- usehi = isPsxRegUsed(pc, REG_HI);
-
- if (IsConst(_Rt_)) {
- int shift = DoShift(iRegs[_Rt_].k);
- if (shift != -1) {
- SRAWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift);
- ADDZE(PutHWReg32(REG_LO), GetHWReg32(REG_LO));
- if (usehi) {
- RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31);
- }
- } else if (iRegs[_Rt_].k == 3) {
- // http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html
- LIS(PutHWReg32(REG_HI), 0x5555);
- ADDI(PutHWReg32(REG_HI), GetHWReg32(REG_HI), 0x5556);
- MULHW(PutHWReg32(REG_LO), GetHWReg32(REG_HI), GetHWReg32(_Rs_));
- SRWI(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 31);
- ADD(PutHWReg32(REG_LO), GetHWReg32(REG_LO), GetHWReg32(REG_HI));
- if (usehi) {
- MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), 3);
- SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
- }
- } else {
- DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- if (usehi) {
- if ((iRegs[_Rt_].k & 0x7fff) == iRegs[_Rt_].k) {
- MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), iRegs[_Rt_].k);
- } else {
- MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_));
- }
- SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
- }
- }
- } else {
- DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- if (usehi) {
- MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_));
- SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
- }
- }
-}
-
-static void recDIVU() {
-// Lo/Hi = Rs / Rt (unsigned)
- int usehi;
-
- if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) {
- MapConst(REG_LO, 0);
- MapConst(REG_HI, 0);
- return;
- }
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(REG_LO, (u32)iRegs[_Rs_].k / (u32)iRegs[_Rt_].k);
- MapConst(REG_HI, (u32)iRegs[_Rs_].k % (u32)iRegs[_Rt_].k);
- return;
- }
-
- usehi = isPsxRegUsed(pc, REG_HI);
-
- if (IsConst(_Rt_)) {
- int shift = DoShift(iRegs[_Rt_].k);
- if (shift != -1) {
- SRWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift);
- if (usehi) {
- RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31);
- }
- } else {
- DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- if (usehi) {
- MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO));
- SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
- }
- }
- } else {
- DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- if (usehi) {
- MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO));
- SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
- }
- }
-}
-#endif
-//End of * Register mult/div & Register trap logic
-
-#pragma mark - memory access -
-
-#if 0
-REC_FUNC(LB);
-REC_FUNC(LBU);
-REC_FUNC(LH);
-REC_FUNC(LHU);
-REC_FUNC(LW);
-
-REC_FUNC(SB);
-REC_FUNC(SH);
-REC_FUNC(SW);
-
-REC_FUNC(LWL);
-REC_FUNC(LWR);
-REC_FUNC(SWL);
-REC_FUNC(SWR);
-#else
-static void preMemRead()
-{
- int rs;
-
- ReserveArgs(1);
- if (_Rs_ != _Rt_) {
- DisposeHWReg(iRegs[_Rt_].reg);
- }
- rs = GetHWReg32(_Rs_);
- if (rs != 3 || _Imm_ != 0) {
- ADDI(PutHWRegSpecial(ARG1), rs, _Imm_);
- }
- if (_Rs_ == _Rt_) {
- DisposeHWReg(iRegs[_Rt_].reg);
- }
- InvalidateCPURegs();
- //FlushAllHWReg();
-}
-
-static void preMemWrite(int size)
-{
- int rs;
-
- ReserveArgs(2);
- rs = GetHWReg32(_Rs_);
- if (rs != 3 || _Imm_ != 0) {
- ADDI(PutHWRegSpecial(ARG1), rs, _Imm_);
- }
- if (size == 1) {
- RLWINM(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0, 24, 31);
- //ANDI_(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0xff);
- } else if (size == 2) {
- RLWINM(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0, 16, 31);
- //ANDI_(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0xffff);
- } else {
- MR(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_));
- }
-
- InvalidateCPURegs();
- //FlushAllHWReg();
-}
-
-static void recLB() {
-// Rt = mem[Rs + Im] (signed)
-
- /*if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRs8(addr));
- return;
- }
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (!_Rt_) return;
-
- addr = (u32)&psxM[addr & 0x1fffff];
- LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
- LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
- EXTSB(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
-
- addr = (u32)&psxH[addr & 0xfff];
- LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
- LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
- EXTSB(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
- return;
- }
- // SysPrintf("unhandled r8 %x\n", addr);
- }*/
-
- preMemRead();
- CALLFunc((u32)psxMemRead8);
- if (_Rt_) {
- EXTSB(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL));
- DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL));
- }
-}
-
-static void recLBU() {
-// Rt = mem[Rs + Im] (unsigned)
-
- /*if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu8(addr));
- return;
- }
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (!_Rt_) return;
-
- addr = (u32)&psxM[addr & 0x1fffff];
- LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
- LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
-
- addr = (u32)&psxH[addr & 0xfff];
- LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
- LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
- return;
- }
- // SysPrintf("unhandled r8 %x\n", addr);
- }*/
-
- preMemRead();
- CALLFunc((u32)psxMemRead8);
-
- if (_Rt_) {
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- }
-}
-
-static void recLH() {
-// Rt = mem[Rs + Im] (signed)
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRs16(addr));
- return;
- }
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
- LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
- LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
- return;
- }
- // SysPrintf("unhandled r16 %x\n", addr);
- }
-
- preMemRead();
- CALLFunc((u32)psxMemRead16);
- if (_Rt_) {
- EXTSH(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL));
- DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL));
- }
-}
-
-static void recLHU() {
-// Rt = mem[Rs + Im] (unsigned)
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu16(addr));
- return;
- }
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
- LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
- LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80) {
- if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
- if (!_Rt_) return;
-
- ReserveArgs(1);
- LIW(PutHWRegSpecial(ARG1), addr);
- DisposeHWReg(iRegs[_Rt_].reg);
- InvalidateCPURegs();
- CALLFunc((u32)SPU_readRegister);
-
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- return;
- }
- switch (addr) {
- case 0x1f801100: case 0x1f801110: case 0x1f801120:
- if (!_Rt_) return;
-
- ReserveArgs(1);
- LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
- DisposeHWReg(iRegs[_Rt_].reg);
- InvalidateCPURegs();
- CALLFunc((u32)psxRcntRcount);
-
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- return;
-
- case 0x1f801104: case 0x1f801114: case 0x1f801124:
- if (!_Rt_) return;
-
- ReserveArgs(1);
- LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
- DisposeHWReg(iRegs[_Rt_].reg);
- InvalidateCPURegs();
- CALLFunc((u32)psxRcntRmode);
-
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- return;
-
- case 0x1f801108: case 0x1f801118: case 0x1f801128:
- if (!_Rt_) return;
-
- ReserveArgs(1);
- LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
- DisposeHWReg(iRegs[_Rt_].reg);
- InvalidateCPURegs();
- CALLFunc((u32)psxRcntRtarget);
-
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- return;
- }
- }
- // SysPrintf("unhandled r16u %x\n", addr);
- }
-
- preMemRead();
- CALLFunc((u32)psxMemRead16);
- if (_Rt_) {
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- }
-}
-
-static void recLW() {
-// Rt = mem[Rs + Im] (unsigned)
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- if (!_Rt_) return;
- // since bios is readonly it won't change
- MapConst(_Rt_, psxRu32(addr));
- return;
- }
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
- LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
- LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- return;
- }
- if (t == 0x1f80) {
- switch (addr) {
- case 0x1f801080: case 0x1f801084: case 0x1f801088:
- case 0x1f801090: case 0x1f801094: case 0x1f801098:
- case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8:
- case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8:
- case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8:
- case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8:
- case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8:
- case 0x1f801070: case 0x1f801074:
- case 0x1f8010f0: case 0x1f8010f4:
- if (!_Rt_) return;
-
- LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xffff]);
- LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
- return;
-
- case 0x1f801810:
- if (!_Rt_) return;
-
- DisposeHWReg(iRegs[_Rt_].reg);
- InvalidateCPURegs();
- CALLFunc((u32)GPU_readData);
-
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- return;
-
- case 0x1f801814:
- if (!_Rt_) return;
-
- DisposeHWReg(iRegs[_Rt_].reg);
- InvalidateCPURegs();
- CALLFunc((u32)GPU_readStatus);
-
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- return;
- }
- }
-// SysPrintf("unhandled r32 %x\n", addr);
- }
-
- preMemRead();
- CALLFunc((u32)psxMemRead32);
- if (_Rt_) {
- SetDstCPUReg(3);
- PutHWReg32(_Rt_);
- }
-}
-
-REC_FUNC(LWL);
-REC_FUNC(LWR);
-REC_FUNC(SWL);
-REC_FUNC(SWR);
-/*extern u32 LWL_MASK[4];
-extern u32 LWL_SHIFT[4];
-
-void iLWLk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32ItoR(ECX, LWL_MASK[shift]);
- SHL32ItoR(EAX, LWL_SHIFT[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recLWL() {
-// Rt = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iLWLk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iLWLk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
- CALLFunc((u32)psxMemRead32);
-
- if (_Rt_) {
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)LWL_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
-
- MOV32ItoR(ECX, (u32)LWL_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
-
- OR32RtoR(EAX, EDX);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- } else {
-// ADD32ItoR(ESP, 8);
- resp+= 8;
- }
-}
-
-static void recLWBlock(int count) {
- u32 *code = PSXM(pc);
- int i, respsave;
-// Rt = mem[Rs + Im] (unsigned)
-
-// iFlushRegs(0);
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0xfff0) == 0xbfc0) {
- // since bios is readonly it won't change
- for (i=0; i<count; i++, code++, addr+=4) {
- if (_fRt_(*code)) {
- MapConst(_fRt_(*code), psxRu32(addr));
- }
- }
- return;
- }
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (!_fRt_(*code)) return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (!_fRt_(*code)) return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- }
-
- SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
- iPushOfB();
- CALLFunc((u32)psxMemPointer);
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-
- respsave = resp; resp = 0;
- TEST32RtoR(EAX, EAX);
- j32Ptr[4] = JZ32(0);
- XOR32RtoR(ECX, ECX);
- for (i=0; i<count; i++, code++) {
- if (_fRt_(*code)) {
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32RmStoR(EDX, EAX, ECX, 2);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX);
- }
- if (i != (count-1)) INC32R(ECX);
- }
- j32Ptr[5] = JMP32(0);
- x86SetJ32(j32Ptr[4]);
- for (i=0, code = PSXM(pc); i<count; i++, code++) {
- psxRegs.code = *code;
- recLW();
- }
- ADD32ItoR(ESP, resp);
- x86SetJ32(j32Ptr[5]);
- resp = respsave;
-}
-
-extern u32 LWR_MASK[4];
-extern u32 LWR_SHIFT[4];
-
-void iLWRk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32ItoR(ECX, LWR_MASK[shift]);
- SHR32ItoR(EAX, LWR_SHIFT[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recLWR() {
-// Rt = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iLWRk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iLWRk(addr & 3);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
- CALLFunc((u32)psxMemRead32);
-
- if (_Rt_) {
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)LWR_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
-
- MOV32ItoR(ECX, (u32)LWR_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
-
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
-
- OR32RtoR(EAX, EDX);
-
- iRegs[_Rt_].state = ST_UNK;
- MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
- } else {
-// ADD32ItoR(ESP, 8);
- resp+= 8;
- }
-}*/
-
-static void recSB() {
-// mem[Rs + Im] = Rt
-
- /*if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
- } else {
- MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
- } else {
- MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV8RtoM((u32)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
-// SysPrintf("unhandled w8 %x\n", addr);
- }*/
-
- preMemWrite(1);
- CALLFunc((u32)psxMemWrite8);
-}
-
-static void recSH() {
-// mem[Rs + Im] = Rt
-
- /*if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- if (IsConst(_Rt_)) {
- MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
- } else {
- MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- if (IsConst(_Rt_)) {
- MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
- } else {
- MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
- MOV16RtoM((u32)&psxH[addr & 0xfff], EAX);
- }
- return;
- }
- if (t == 0x1f80) {
- if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
- if (IsConst(_Rt_)) {
- PUSH32I(iRegs[_Rt_].k);
- } else {
- PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
- }
- PUSH32I (addr);
- CALL32M ((u32)&SPU_writeRegister);
-#ifndef __WIN32__
- resp+= 8;
-#endif
- return;
- }
- }
-// SysPrintf("unhandled w16 %x\n", addr);
- }*/
-
- preMemWrite(2);
- CALLFunc((u32)psxMemWrite16);
-}
-
-static void recSW() {
-// mem[Rs + Im] = Rt
- u32 *b1, *b2;
-#if 0
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- LIW(0, addr & 0x1fffff);
- STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- LIW(0, (u32)&psxH[addr & 0xfff]);
- STWBRX(GetHWReg32(_Rt_), 0, 0);
- return;
- }
- if (t == 0x1f80) {
- switch (addr) {
- case 0x1f801080: case 0x1f801084:
- case 0x1f801090: case 0x1f801094:
- case 0x1f8010a0: case 0x1f8010a4:
- case 0x1f8010b0: case 0x1f8010b4:
- case 0x1f8010c0: case 0x1f8010c4:
- case 0x1f8010d0: case 0x1f8010d4:
- case 0x1f8010e0: case 0x1f8010e4:
- case 0x1f801074:
- case 0x1f8010f0:
- LIW(0, (u32)&psxH[addr & 0xffff]);
- STWBRX(GetHWReg32(_Rt_), 0, 0);
- return;
-
-/* case 0x1f801810:
- if (IsConst(_Rt_)) {
- PUSH32I(iRegs[_Rt_].k);
- } else {
- PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
- }
- CALL32M((u32)&GPU_writeData);
-#ifndef __WIN32__
- resp+= 4;
-#endif
- return;
-
- case 0x1f801814:
- if (IsConst(_Rt_)) {
- PUSH32I(iRegs[_Rt_].k);
- } else {
- PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
- }
- CALL32M((u32)&GPU_writeStatus);
-#ifndef __WIN32__
- resp+= 4;
-#endif*/
- }
- }
-// SysPrintf("unhandled w32 %x\n", addr);
- }
-
-/* LIS(0, 0x0079 + ((_Imm_ <= 0) ? 1 : 0));
- CMPLW(GetHWReg32(_Rs_), 0);
- BGE_L(b1);
-
- //SaveContext();
- ADDI(0, GetHWReg32(_Rs_), _Imm_);
- RLWINM(0, GetHWReg32(_Rs_), 0, 11, 31);
- STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0);
- B_L(b2);
-
- B_DST(b1);*/
-#endif
- preMemWrite(4);
- CALLFunc((u32)psxMemWrite32);
-
- //B_DST(b2);
-}
-
-/*
-static void recSWBlock(int count) {
- u32 *code;
- int i, respsave;
-// mem[Rs + Im] = Rt
-
-// iFlushRegs();
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
- code = PSXM(pc);
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (IsConst(_fRt_(*code))) {
- MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k);
- } else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
- MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
- }
- }
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- for (i=0; i<count; i++, code++, addr+=4) {
- if (!_fRt_(*code)) return;
- iRegs[_fRt_(*code)].state = ST_UNK;
-
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
- MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
- }
- return;
- }
- }
-
- SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
- iPushOfB();
- CALLFunc((u32)psxMemPointer);
-// ADD32ItoR(ESP, 4);
- resp+= 4;
-
- respsave = resp; resp = 0;
- TEST32RtoR(EAX, EAX);
- j32Ptr[4] = JZ32(0);
- XOR32RtoR(ECX, ECX);
- for (i=0, code = PSXM(pc); i<count; i++, code++) {
- if (IsConst(_fRt_(*code))) {
- MOV32ItoR(EDX, iRegs[_fRt_(*code)].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
- }
- MOV32RtoRmS(EAX, ECX, 2, EDX);
- if (i != (count-1)) INC32R(ECX);
- }
- j32Ptr[5] = JMP32(0);
- x86SetJ32(j32Ptr[4]);
- for (i=0, code = PSXM(pc); i<count; i++, code++) {
- psxRegs.code = *code;
- recSW();
- }
- ADD32ItoR(ESP, resp);
- x86SetJ32(j32Ptr[5]);
- resp = respsave;
-}
-
-extern u32 SWL_MASK[4];
-extern u32 SWL_SHIFT[4];
-
-void iSWLk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHR32ItoR(ECX, SWL_SHIFT[shift]);
- AND32ItoR(EAX, SWL_MASK[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recSWL() {
-// mem[Rs + Im] = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iSWLk(addr & 3);
- MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iSWLk(addr & 3);
- MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemRead32);
-
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)SWL_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
-
- MOV32ItoR(ECX, (u32)SWL_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
-
- OR32RtoR (EAX, EDX);
- PUSH32R (EAX);
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- resp+= 8;
-}
-
-extern u32 SWR_MASK[4];
-extern u32 SWR_SHIFT[4];
-
-void iSWRk(u32 shift) {
- if (IsConst(_Rt_)) {
- MOV32ItoR(ECX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHL32ItoR(ECX, SWR_SHIFT[shift]);
- AND32ItoR(EAX, SWR_MASK[shift]);
- OR32RtoR (EAX, ECX);
-}
-
-void recSWR() {
-// mem[Rs + Im] = Rt Merge mem[Rs + Im]
-
- if (IsConst(_Rs_)) {
- u32 addr = iRegs[_Rs_].k + _Imm_;
- int t = addr >> 16;
-
- if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
- MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
- iSWRk(addr & 3);
- MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
- return;
- }
- if (t == 0x1f80 && addr < 0x1f801000) {
- MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
- iSWRk(addr & 3);
- MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
- return;
- }
- }
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- PUSH32R (EAX);
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemRead32);
-
- ADD32ItoR(ESP, 4);
- POP32R (EDX);
- AND32ItoR(EDX, 0x3); // shift = addr & 3;
-
- MOV32ItoR(ECX, (u32)SWR_MASK);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
-
- MOV32ItoR(ECX, (u32)SWR_SHIFT);
- MOV32RmStoR(ECX, ECX, EDX, 2);
- if (IsConst(_Rt_)) {
- MOV32ItoR(EDX, iRegs[_Rt_].k);
- } else {
- MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
- }
- SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
-
- OR32RtoR (EAX, EDX);
- PUSH32R (EAX);
-
- if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
- else {
- MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
- if (_Imm_) ADD32ItoR(EAX, _Imm_);
- }
- AND32ItoR(EAX, ~3);
- PUSH32R (EAX);
-
- CALLFunc((u32)psxMemWrite32);
-// ADD32ItoR(ESP, 8);
- resp+= 8;
-}*/
-#endif
-
-#if 0
-/*REC_FUNC(SLL);
-REC_FUNC(SRL);
-REC_FUNC(SRA);*/
-#else
-static void recSLL() {
-// Rd = Rt << Sa
- if (!_Rd_) return;
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
- } else {
- SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
- }
-}
-
-static void recSRL() {
-// Rd = Rt >> Sa
- if (!_Rd_) return;
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
- } else {
- SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
- }
-}
-
-static void recSRA() {
-// Rd = Rt >> Sa
- if (!_Rd_) return;
-
- if (IsConst(_Rt_)) {
- MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
- } else {
- SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
- }
-}
-#endif
-
-#pragma mark - shift ops -
-#if 0
-/*REC_FUNC(SLLV);
-REC_FUNC(SRLV);
-REC_FUNC(SRAV);*/
-#else
-static void recSLLV() {
-// Rd = Rt << Rs
- if (!_Rd_) return;
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k);
- } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- SLW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
- }
-}
-
-static void recSRLV() {
-// Rd = Rt >> Rs
- if (!_Rd_) return;
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k);
- } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- SRW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
- }
-}
-
-static void recSRAV() {
-// Rd = Rt >> Rs
- if (!_Rd_) return;
-
- if (IsConst(_Rt_) && IsConst(_Rs_)) {
- MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k);
- } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
- } else {
- SRAW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
- }
-}
-#endif
-
-//REC_SYS(SYSCALL);
-//REC_SYS(BREAK);
-
-//#if 0*/
-/*int dump;*/
-static void recSYSCALL() {
-// dump=1;
- iFlushRegs(0);
-
- ReserveArgs(2);
- LIW(PutHWRegSpecial(PSXPC), pc - 4);
- LIW(PutHWRegSpecial(ARG1), 0x20);
- LIW(PutHWRegSpecial(ARG2), (branch == 1 ? 1 : 0));
- FlushAllHWReg();
- CALLFunc ((u32)psxException);
-
- branch = 2;
- iRet();
-}
-
-static void recBREAK() {
-}
-//#endif
-
-#if 0
-/*REC_FUNC(MFHI);
-REC_FUNC(MTHI);
-REC_FUNC(MFLO);
-REC_FUNC(MTLO);*/
-#else
-static void recMFHI() {
-// Rd = Hi
- if (!_Rd_) return;
-
- if (IsConst(REG_HI)) {
- MapConst(_Rd_, iRegs[REG_HI].k);
- } else {
- MapCopy(_Rd_, REG_HI);
- }
-}
-
-static void recMTHI() {
-// Hi = Rs
-
- if (IsConst(_Rs_)) {
- MapConst(REG_HI, iRegs[_Rs_].k);
- } else {
- MapCopy(REG_HI, _Rs_);
- }
-}
-
-static void recMFLO() {
-// Rd = Lo
- if (!_Rd_) return;
-
- if (IsConst(REG_LO)) {
- MapConst(_Rd_, iRegs[REG_LO].k);
- } else {
- MapCopy(_Rd_, REG_LO);
- }
-}
-
-static void recMTLO() {
-// Lo = Rs
-
- if (IsConst(_Rs_)) {
- MapConst(REG_LO, iRegs[_Rs_].k);
- } else {
- MapCopy(REG_LO, _Rs_);
- }
-}
-#endif
-
-#pragma mark - branch ops -
-#if 0
-/*REC_BRANCH(J);
-REC_BRANCH(JR);
-REC_BRANCH(JAL);
-REC_BRANCH(JALR);
-REC_BRANCH(BLTZ);
-REC_BRANCH(BGTZ);
-REC_BRANCH(BLTZAL);
-REC_BRANCH(BGEZAL);
-REC_BRANCH(BNE);
-REC_BRANCH(BEQ);
-REC_BRANCH(BLEZ);
-REC_BRANCH(BGEZ);*/
-#else
-static void recBLTZ() {
-// Branch if Rs < 0
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k < 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMPWI(GetHWReg32(_Rs_), 0);
- BLT_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBGTZ() {
-// Branch if Rs > 0
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k > 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMPWI(GetHWReg32(_Rs_), 0);
- BGT_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBLTZAL() {
-// Branch if Rs < 0
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k < 0) {
- MapConst(31, pc + 4);
-
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMPWI(GetHWReg32(_Rs_), 0);
- BLT_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- MapConst(31, pc + 4);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBGEZAL() {
-// Branch if Rs >= 0
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k >= 0) {
- MapConst(31, pc + 4);
-
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMPWI(GetHWReg32(_Rs_), 0);
- BGE_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- MapConst(31, pc + 4);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recJ() {
-// j target
-
- iJump(_Target_ * 4 + (pc & 0xf0000000));
-}
-
-static void recJAL() {
-// jal target
- MapConst(31, pc + 4);
-
- iJump(_Target_ * 4 + (pc & 0xf0000000));
-}
-
-static void recJR() {
-// jr Rs
-
- if (IsConst(_Rs_)) {
- iJump(iRegs[_Rs_].k);
- //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k);
- } else {
- MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_));
- SetBranch();
- }
-}
-
-static void recJALR() {
-// jalr Rs
-
- if (_Rd_) {
- MapConst(_Rd_, pc + 4);
- }
-
- if (IsConst(_Rs_)) {
- iJump(iRegs[_Rs_].k);
- //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k);
- } else {
- MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_));
- SetBranch();
- }
-}
-
-static void recBEQ() {
-// Branch if Rs == Rt
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (_Rs_ == _Rt_) {
- iJump(bpc);
- }
- else {
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
- else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
- CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
- }
- else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
- CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
- }
- else {
- CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
- CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
- }
- else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
- CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
- }
- else {
- CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- else {
- CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-
- BEQ_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- iBranch(bpc, 0);
- pc+=4;
- }
-}
-
-static void recBNE() {
-// Branch if Rs != Rt
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (_Rs_ == _Rt_) {
- iJump(pc+4);
- }
- else {
- if (IsConst(_Rs_) && IsConst(_Rt_)) {
- if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
- else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
- if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
- CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
- }
- else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
- CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
- }
- else {
- CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
- if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
- CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
- }
- else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
- CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
- }
- else {
- CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
- }
- else {
- CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
- }
-
- BNE_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- iBranch(bpc, 0);
- pc+=4;
- }
-}
-
-static void recBLEZ() {
-// Branch if Rs <= 0
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k <= 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMPWI(GetHWReg32(_Rs_), 0);
- BLE_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-
-static void recBGEZ() {
-// Branch if Rs >= 0
- u32 bpc = _Imm_ * 4 + pc;
- u32 *b;
-
- if (IsConst(_Rs_)) {
- if ((s32)iRegs[_Rs_].k >= 0) {
- iJump(bpc); return;
- } else {
- iJump(pc+4); return;
- }
- }
-
- CMPWI(GetHWReg32(_Rs_), 0);
- BGE_L(b);
-
- iBranch(pc+4, 1);
-
- B_DST(b);
-
- iBranch(bpc, 0);
- pc+=4;
-}
-#endif
-
-#if 1
-//REC_FUNC(MFC0);
-//REC_SYS(MTC0);
-//REC_FUNC(CFC0);
-//REC_SYS(CTC0);
-REC_FUNC(RFE);
-//#else
-static void recMFC0() {
-// Rt = Cop0->Rd
- if (!_Rt_) return;
-
- LWZ(PutHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
-}
-
-static void recCFC0() {
-// Rt = Cop0->Rd
-
- recMFC0();
-}
-
-static void recMTC0() {
-// Cop0->Rd = Rt
-
- /*if (IsConst(_Rt_)) {
- switch (_Rd_) {
- case 12:
- MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
- break;
- case 13:
- MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
- break;
- default:
- MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
- break;
- }
- } else*/ {
- switch (_Rd_) {
- case 13:
- RLWINM(0,GetHWReg32(_Rt_),0,22,15); // & ~(0xfc00)
- STW(0, OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
- break;
- default:
- STW(GetHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
- break;
- }
- }
-
- if (_Rd_ == 12 || _Rd_ == 13) {
- iFlushRegs(0);
- LIW(PutHWRegSpecial(PSXPC), (u32)pc);
- FlushAllHWReg();
- CALLFunc((u32)psxTestSWInts);
- if(_Rd_ == 12) {
- LWZ(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS));
- ORIS(0, 0, 0x8000);
- STW(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS));
- }
- branch = 2;
- iRet();
- }
-}
-
-static void recCTC0() {
-// Cop0->Rd = Rt
-
- recMTC0();
-}
-#else
-static void recRFE() {
- // TODO: implement multiple temp registers or cop0 registers
- RLWINM(t1,Status,0,0,27);
- RLWINM(Status,Status,30,28,31);
- OR(Status,t1,Status);
-
- MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
- MOV32RtoR(ECX, EAX);
- AND32ItoR(EAX, 0xfffffff0);
- AND32ItoR(ECX, 0x3c);
- SHR32ItoR(ECX, 2);
- OR32RtoR (EAX, ECX);
- MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX);
- CALLFunc((u32)psxExceptionTest);
-}
-#endif
-
-#if 0
-#define CP2_FUNC(f) \
-void gte##f(); \
-static void rec##f() { \
- iFlushRegs(0); \
- LIW(0, (u32)psxRegs.code); \
- STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
- FlushAllHWReg(); \
- CALLFunc ((u32)gte##f); \
-}
-CP2_FUNC(LWC2);
-CP2_FUNC(SWC2);
-
-#else
-#include "pGte.h"
-#endif
-//
-
-static void recHLE() {
- iFlushRegs(0);
- FlushAllHWReg();
-
- if ((psxRegs.code & 0x3ffffff) == (psxRegs.code & 0x7)) {
- CALLFunc((u32)psxHLEt[psxRegs.code & 0x7]);
- } else {
- // somebody else must have written to current opcode for this to happen!!!!
- CALLFunc((u32)psxHLEt[0]); // call dummy function
- }
-
- count = (idlecyclecount + (pc - pcold) / 4 + 20) * BIAS;
- ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
- FlushAllHWReg();
- CALLFunc((u32)psxBranchTest);
- Return();
-
- branch = 2;
-}
-
-//
-
-static void (*recBSC[64])() = {
- recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
- recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI ,
- recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
- recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL,
- recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL,
- recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recSPC[64])() = {
- recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV,
- recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
- recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL,
- recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL,
- recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR ,
- recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL
-};
-
-static void (*recREG[32])() = {
- recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recCP0[32])() = {
- recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
- recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
-};
-
-static void (*recCP2[64])() = {
- recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00
- recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08
- recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10
- recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18
- recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20
- recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28
- recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30
- recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38
-};
-
-static void (*recCP2BSC[32])() = {
- recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, 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
-};
-
-static void recRecompile() {
- //static int recCount = 0;
- char *p;
- u32 *ptr;
- int i;
-
- cop2readypc = 0;
- idlecyclecount = 0;
-
- // initialize state variables
- UniqueRegAlloc = 1;
- HWRegUseCount = 0;
- DstCPUReg = -1;
- memset(HWRegisters, 0, sizeof(HWRegisters));
- for (i=0; i<NUM_HW_REGISTERS; i++)
- HWRegisters[i].code = cpuHWRegisters[NUM_HW_REGISTERS-i-1];
-
- // reserve the special psxReg register
- HWRegisters[0].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
- HWRegisters[0].private = PSXREGS;
- HWRegisters[0].k = (u32)&psxRegs;
-
- HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
- HWRegisters[1].private = PSXMEM;
- HWRegisters[1].k = (u32)&psxM;
-
- // reserve the special psxRegs.cycle register
- //HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
- //HWRegisters[1].private = CYCLECOUNT;
-
- //memset(iRegs, 0, sizeof(iRegs));
- for (i=0; i<NUM_REGISTERS; i++) {
- iRegs[i].state = ST_UNK;
- iRegs[i].reg = -1;
- }
- iRegs[0].k = 0;
- iRegs[0].state = ST_CONST;
-
- /* if ppcPtr reached the mem limit reset whole mem */
- if (((u32)ppcPtr - (u32)recMem) >= (RECMEM_SIZE - 0x10000))
- recReset();
-
- ppcAlign(/*32*/4);
- ptr = ppcPtr;
-
- // give us write access
- //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE);
-
- // tell the LUT where to find us
- PC_REC32(psxRegs.pc) = (u32)ppcPtr;
-
- pcold = pc = psxRegs.pc;
-
- //SysPrintf("RecCount: %i\n", recCount++);
-
- for (count=0; count<500;) {
- p = (char *)PSXM(pc);
- if (p == NULL) recError();
- psxRegs.code = SWAP32(*(u32 *)p);
-/*
- if ((psxRegs.code >> 26) == 0x23) { // LW
- int i;
- u32 code;
-
- for (i=1;; i++) {
- p = (char *)PSXM(pc+i*4);
- if (p == NULL) recError();
- code = *(u32 *)p;
-
- if ((code >> 26) != 0x23 ||
- _fRs_(code) != _Rs_ ||
- _fImm_(code) != (_Imm_+i*4))
- break;
- }
- if (i > 1) {
- recLWBlock(i);
- pc = pc + i*4; continue;
- }
- }
-
- if ((psxRegs.code >> 26) == 0x2b) { // SW
- int i;
- u32 code;
-
- for (i=1;; i++) {
- p = (char *)PSXM(pc+i*4);
- if (p == NULL) recError();
- code = *(u32 *)p;
-
- if ((code >> 26) != 0x2b ||
- _fRs_(code) != _Rs_ ||
- _fImm_(code) != (_Imm_+i*4))
- break;
- }
- if (i > 1) {
- recSWBlock(i);
- pc = pc + i*4; continue;
- }
- }*/
-
- pc+=4; count++;
-// iFlushRegs(0); // test
- recBSC[psxRegs.code>>26]();
-
- if (branch) {
- branch = 0;
- //if (dump) iDumpBlock(ptr);
- goto done;
- }
- }
-
- iFlushRegs(pc);
-
- LIW(PutHWRegSpecial(PSXPC), pc);
-
- iRet();
-
-done:;
-#if 0
- MakeDataExecutable(ptr, ((u8*)ppcPtr)-((u8*)ptr));
-#else
- u32 a = (u32)(u8*)ptr;
- while(a < (u32)(u8*)ppcPtr) {
- __asm__ __volatile__("icbi 0,%0" : : "r" (a));
- __asm__ __volatile__("dcbst 0,%0" : : "r" (a));
- a += 4;
- }
- __asm__ __volatile__("sync");
- __asm__ __volatile__("isync");
-#endif
-
-#if 1
- sprintf((char *)ppcPtr, "PC=%08x", pcold);
- ppcPtr += strlen((char *)ppcPtr);
-#endif
-
- //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ/*|PROT_WRITE*/);
-}
-
-
-R3000Acpu psxRec = {
- recInit,
- recReset,
- recExecute,
- recExecuteBlock,
- recClear,
- recShutdown
-};
-
-#endif
+/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2003 Pcsx 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__) || defined (__powerpc64__) || defined (__POWERPC__) + +#ifdef _MSC_VER_ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/mman.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +#include "../psxcommon.h" +#include "ppc.h" +#include "reguse.h" +#include "../r3000a.h" +#include "../psxhle.h" + +//#define NO_CONSTANT + +u32 *psxRecLUT; + +#undef _Op_ +#define _Op_ _fOp_(psxRegs.code) +#undef _Funct_ +#define _Funct_ _fFunct_(psxRegs.code) +#undef _Rd_ +#define _Rd_ _fRd_(psxRegs.code) +#undef _Rt_ +#define _Rt_ _fRt_(psxRegs.code) +#undef _Rs_ +#define _Rs_ _fRs_(psxRegs.code) +#undef _Sa_ +#define _Sa_ _fSa_(psxRegs.code) +#undef _Im_ +#define _Im_ _fIm_(psxRegs.code) +#undef _Target_ +#define _Target_ _fTarget_(psxRegs.code) + +#undef _Imm_ +#define _Imm_ _fImm_(psxRegs.code) +#undef _ImmU_ +#define _ImmU_ _fImmU_(psxRegs.code) + +#undef PC_REC +#undef PC_REC8 +#undef PC_REC16 +#undef PC_REC32 +#define PC_REC(x) (psxRecLUT[x >> 16] + (x & 0xffff)) +#define PC_REC8(x) (*(u8 *)PC_REC(x)) +#define PC_REC16(x) (*(u16*)PC_REC(x)) +#define PC_REC32(x) (*(u32*)PC_REC(x)) + +#define OFFSET(X,Y) ((u32)(Y)-(u32)(X)) + +#define RECMEM_SIZE (12*1024*1024) + +static char *recMem; /* the recompiled blocks will be here */ +static char *recRAM; /* and the ptr to the blocks here */ +static char *recROM; /* and here */ + +static u32 pc; /* recompiler pc */ +static u32 pcold; /* recompiler oldpc */ +static int count; /* recompiler intruction count */ +static int branch; /* set for branch */ +static u32 target; /* branch target */ +static u32 resp; + +u32 cop2readypc = 0; +u32 idlecyclecount = 0; + +#define NUM_REGISTERS 34 +typedef struct { + int state; + u32 k; + int reg; +} iRegisters; + +static iRegisters iRegs[34]; + +#define ST_UNK 0x00 +#define ST_CONST 0x01 +#define ST_MAPPED 0x02 + +#ifdef NO_CONSTANT +#define IsConst(reg) 0 +#else +#define IsConst(reg) (iRegs[reg].state & ST_CONST) +#endif +#define IsMapped(reg) (iRegs[reg].state & ST_MAPPED) + +static void (*recBSC[64])(); +static void (*recSPC[64])(); +static void (*recREG[32])(); +static void (*recCP0[32])(); +static void (*recCP2[64])(); +static void (*recCP2BSC[32])(); + +#define REG_LO 32 +#define REG_HI 33 + +// Hardware register usage +#define HWUSAGE_NONE 0x00 + +#define HWUSAGE_READ 0x01 +#define HWUSAGE_WRITE 0x02 +#define HWUSAGE_CONST 0x04 +#define HWUSAGE_ARG 0x08 /* used as an argument for a function call */ + +#define HWUSAGE_RESERVED 0x10 /* won't get flushed when flushing all regs */ +#define HWUSAGE_SPECIAL 0x20 /* special purpose register */ +#define HWUSAGE_HARDWIRED 0x40 /* specific hardware register mapping that is never disposed */ +#define HWUSAGE_INITED 0x80 +#define HWUSAGE_PSXREG 0x100 + +// Remember to invalidate the special registers if they are modified by compiler +enum { + ARG1 = 3, + ARG2 = 4, + ARG3 = 5, + PSXREGS, // ptr + PSXMEM, // ptr + CYCLECOUNT, // ptr + PSXPC, // ptr + TARGETPTR, // ptr + TARGET, // ptr + RETVAL, + REG_RZERO, + REG_WZERO +}; + +typedef struct { + int code; + u32 k; + int usage; + int lastUsed; + + void (*flush)(int hwreg); + int private; +} HWRegister; +static HWRegister HWRegisters[NUM_HW_REGISTERS]; +static int HWRegUseCount; +static int DstCPUReg; +static int UniqueRegAlloc; + +static int GetFreeHWReg(); +static void InvalidateCPURegs(); +static void DisposeHWReg(int index); +static void FlushHWReg(int index); +static void FlushAllHWReg(); +static void MapPsxReg32(int reg); +static void FlushPsxReg32(int hwreg); +static int UpdateHWRegUsage(int hwreg, int usage); +static int GetHWReg32(int reg); +static int PutHWReg32(int reg); +static int GetSpecialIndexFromHWRegs(int which); +static int GetHWRegFromCPUReg(int cpureg); +static int MapRegSpecial(int which); +static void FlushRegSpecial(int hwreg); +static int GetHWRegSpecial(int which); +static int PutHWRegSpecial(int which); +static void recRecompile(); +static void recError(); + +#pragma mark --- Generic register mapping --- + +static int GetFreeHWReg() +{ + int i, least, index; + + if (DstCPUReg != -1) { + index = GetHWRegFromCPUReg(DstCPUReg); + DstCPUReg = -1; + } else { + // LRU algorith with a twist ;) + for (i=0; i<NUM_HW_REGISTERS; i++) { + if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) { + break; + } + } + + least = HWRegisters[i].lastUsed; index = i; + for (; i<NUM_HW_REGISTERS; i++) { + if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) { + if (HWRegisters[i].usage == HWUSAGE_NONE && HWRegisters[i].code >= 13) { + index = i; + break; + } + else if (HWRegisters[i].lastUsed < least) { + least = HWRegisters[i].lastUsed; + index = i; + } + } + } + + // Cycle the registers + if (HWRegisters[index].usage == HWUSAGE_NONE) { + for (; i<NUM_HW_REGISTERS; i++) { + if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) { + if (HWRegisters[i].usage == HWUSAGE_NONE && + HWRegisters[i].code >= 13 && + HWRegisters[i].lastUsed < least) { + least = HWRegisters[i].lastUsed; + index = i; + break; + } + } + } + } + } + +/* if (HWRegisters[index].code < 13 && HWRegisters[index].code > 3) { + SysPrintf("Allocating volatile register %i\n", HWRegisters[index].code); + } + if (HWRegisters[index].usage != HWUSAGE_NONE) { + SysPrintf("RegUse too big. Flushing %i\n", HWRegisters[index].code); + }*/ + if (HWRegisters[index].usage & (HWUSAGE_RESERVED | HWUSAGE_HARDWIRED)) { + if (HWRegisters[index].usage & HWUSAGE_RESERVED) { + SysPrintf("Error! Trying to map a new register to a reserved register (r%i)", + HWRegisters[index].code); + } + if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) { + SysPrintf("Error! Trying to map a new register to a hardwired register (r%i)", + HWRegisters[index].code); + } + } + + if (HWRegisters[index].lastUsed != 0) { + UniqueRegAlloc = 0; + } + + // Make sure the register is really flushed! + FlushHWReg(index); + HWRegisters[index].usage = HWUSAGE_NONE; + HWRegisters[index].flush = NULL; + + return index; +} + +static void FlushHWReg(int index) +{ + if (index < 0) return; + if (HWRegisters[index].usage == HWUSAGE_NONE) return; + + if (HWRegisters[index].flush) { + HWRegisters[index].usage |= HWUSAGE_RESERVED; + HWRegisters[index].flush(index); + HWRegisters[index].flush = NULL; + } + + if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) { + HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE); + } else { + HWRegisters[index].usage = HWUSAGE_NONE; + } +} + +// get rid of a mapped register without flushing the contents to the memory +static void DisposeHWReg(int index) +{ + if (index < 0) return; + if (HWRegisters[index].usage == HWUSAGE_NONE) return; + + HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE); + if (HWRegisters[index].usage == HWUSAGE_NONE) { + SysPrintf("Error! not correctly disposing register (r%i)", HWRegisters[index].code); + } + + FlushHWReg(index); +} + +// operated on cpu registers +__inline static void FlushCPURegRange(int start, int end) +{ + int i; + + if (end <= 0) end = 31; + if (start <= 0) start = 0; + + for (i=0; i<NUM_HW_REGISTERS; i++) { + if (HWRegisters[i].code >= start && HWRegisters[i].code <= end) + if (HWRegisters[i].flush) + FlushHWReg(i); + } + + for (i=0; i<NUM_HW_REGISTERS; i++) { + if (HWRegisters[i].code >= start && HWRegisters[i].code <= end) + FlushHWReg(i); + } +} + +static void FlushAllHWReg() +{ + FlushCPURegRange(0,31); +} + +static void InvalidateCPURegs() +{ + FlushCPURegRange(0,12); +} + +#pragma mark --- Mapping utility functions --- + +static void MoveHWRegToCPUReg(int cpureg, int hwreg) +{ + int dstreg; + + if (HWRegisters[hwreg].code == cpureg) + return; + + dstreg = GetHWRegFromCPUReg(cpureg); + + HWRegisters[dstreg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG); + if (HWRegisters[hwreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) { + FlushHWReg(dstreg); + MR(HWRegisters[dstreg].code, HWRegisters[hwreg].code); + } else { + if (HWRegisters[dstreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) { + MR(HWRegisters[hwreg].code, HWRegisters[dstreg].code); + } + else if (HWRegisters[dstreg].usage != HWUSAGE_NONE) { + FlushHWReg(dstreg); + } + } + + HWRegisters[dstreg].code = HWRegisters[hwreg].code; + HWRegisters[hwreg].code = cpureg; +} + +static int UpdateHWRegUsage(int hwreg, int usage) +{ + HWRegisters[hwreg].lastUsed = ++HWRegUseCount; + if (usage & HWUSAGE_WRITE) { + HWRegisters[hwreg].usage &= ~HWUSAGE_CONST; + } + if (!(usage & HWUSAGE_INITED)) { + HWRegisters[hwreg].usage &= ~HWUSAGE_INITED; + } + HWRegisters[hwreg].usage |= usage; + + return HWRegisters[hwreg].code; +} + +static int GetHWRegFromCPUReg(int cpureg) +{ + int i; + for (i=0; i<NUM_HW_REGISTERS; i++) { + if (HWRegisters[i].code == cpureg) { + return i; + } + } + + SysPrintf("Error! Register location failure (r%i)", cpureg); + return 0; +} + +// this function operates on cpu registers +void SetDstCPUReg(int cpureg) +{ + DstCPUReg = cpureg; +} + +static void ReserveArgs(int args) +{ + int index, i; + + for (i=0; i<args; i++) { + index = GetHWRegFromCPUReg(3+i); + HWRegisters[index].usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG; + } +} + +static void ReleaseArgs() +{ + int i; + + for (i=0; i<NUM_HW_REGISTERS; i++) { + if (HWRegisters[i].usage & HWUSAGE_ARG) { + //HWRegisters[i].usage = HWUSAGE_NONE; + //HWRegisters[i].flush = NULL; + HWRegisters[i].usage &= ~(HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG); + FlushHWReg(i); + } + } +} + +#pragma mark --- Psx register mapping --- + +static void MapPsxReg32(int reg) +{ + int hwreg = GetFreeHWReg(); + HWRegisters[hwreg].flush = FlushPsxReg32; + HWRegisters[hwreg].private = reg; + + if (iRegs[reg].reg != -1) { + SysPrintf("error: double mapped psx register"); + } + + iRegs[reg].reg = hwreg; + iRegs[reg].state |= ST_MAPPED; +} + +static void FlushPsxReg32(int hwreg) +{ + int reg = HWRegisters[hwreg].private; + + if (iRegs[reg].reg == -1) { + SysPrintf("error: flushing unmapped psx register"); + } + + if (HWRegisters[hwreg].usage & HWUSAGE_WRITE) { + if (branch) { + /*int reguse = nextPsxRegUse(pc-8, reg); + if (reguse == REGUSE_NONE || (reguse & REGUSE_READ))*/ { + STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS)); + } + } else { + int reguse = nextPsxRegUse(pc-4, reg); + if (reguse == REGUSE_NONE || (reguse & REGUSE_READ)) { + STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS)); + } + } + } + + iRegs[reg].reg = -1; + iRegs[reg].state = ST_UNK; +} + +static int GetHWReg32(int reg) +{ + int usage = HWUSAGE_PSXREG | HWUSAGE_READ; + + if (reg == 0) { + return GetHWRegSpecial(REG_RZERO); + } + if (!IsMapped(reg)) { + usage |= HWUSAGE_INITED; + MapPsxReg32(reg); + + HWRegisters[iRegs[reg].reg].usage |= HWUSAGE_RESERVED; + if (IsConst(reg)) { + LIW(HWRegisters[iRegs[reg].reg].code, iRegs[reg].k); + usage |= HWUSAGE_WRITE | HWUSAGE_CONST; + //iRegs[reg].state &= ~ST_CONST; + } + else { + LWZ(HWRegisters[iRegs[reg].reg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS)); + } + HWRegisters[iRegs[reg].reg].usage &= ~HWUSAGE_RESERVED; + } + else if (DstCPUReg != -1) { + int dst = DstCPUReg; + DstCPUReg = -1; + + if (HWRegisters[iRegs[reg].reg].code < 13) { + MoveHWRegToCPUReg(dst, iRegs[reg].reg); + } else { + MR(DstCPUReg, HWRegisters[iRegs[reg].reg].code); + } + } + + DstCPUReg = -1; + + return UpdateHWRegUsage(iRegs[reg].reg, usage); +} + +static int PutHWReg32(int reg) +{ + int usage = HWUSAGE_PSXREG | HWUSAGE_WRITE; + if (reg == 0) { + return PutHWRegSpecial(REG_WZERO); + } + + if (DstCPUReg != -1 && IsMapped(reg)) { + if (HWRegisters[iRegs[reg].reg].code != DstCPUReg) { + int tmp = DstCPUReg; + DstCPUReg = -1; + DisposeHWReg(iRegs[reg].reg); + DstCPUReg = tmp; + } + } + if (!IsMapped(reg)) { + usage |= HWUSAGE_INITED; + MapPsxReg32(reg); + } + + DstCPUReg = -1; + iRegs[reg].state &= ~ST_CONST; + + return UpdateHWRegUsage(iRegs[reg].reg, usage); +} + +#pragma mark --- Special register mapping --- + +static int GetSpecialIndexFromHWRegs(int which) +{ + int i; + for (i=0; i<NUM_HW_REGISTERS; i++) { + if (HWRegisters[i].usage & HWUSAGE_SPECIAL) { + if (HWRegisters[i].private == which) { + return i; + } + } + } + return -1; +} + +static int MapRegSpecial(int which) +{ + int hwreg = GetFreeHWReg(); + HWRegisters[hwreg].flush = FlushRegSpecial; + HWRegisters[hwreg].private = which; + + return hwreg; +} + +static void FlushRegSpecial(int hwreg) +{ + int which = HWRegisters[hwreg].private; + + if (!(HWRegisters[hwreg].usage & HWUSAGE_WRITE)) + return; + + switch (which) { + case CYCLECOUNT: + STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS)); + break; + case PSXPC: + STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS)); + break; + case TARGET: + STW(HWRegisters[hwreg].code, 0, GetHWRegSpecial(TARGETPTR)); + break; + } +} + +static int GetHWRegSpecial(int which) +{ + int index = GetSpecialIndexFromHWRegs(which); + int usage = HWUSAGE_READ | HWUSAGE_SPECIAL; + + if (index == -1) { + usage |= HWUSAGE_INITED; + index = MapRegSpecial(which); + + HWRegisters[index].usage |= HWUSAGE_RESERVED; + switch (which) { + case PSXREGS: + case PSXMEM: + SysPrintf("error! shouldn't be here!\n"); + //HWRegisters[index].flush = NULL; + //LIW(HWRegisters[index].code, (u32)&psxRegs); + break; + case TARGETPTR: + HWRegisters[index].flush = NULL; + LIW(HWRegisters[index].code, (u32)&target); + break; + case REG_RZERO: + HWRegisters[index].flush = NULL; + LIW(HWRegisters[index].code, 0); + break; + case RETVAL: + MoveHWRegToCPUReg(3, index); + /*reg = GetHWRegFromCPUReg(3); + HWRegisters[reg].code = HWRegisters[index].code; + HWRegisters[index].code = 3;*/ + HWRegisters[index].flush = NULL; + + usage |= HWUSAGE_RESERVED; + break; + + case CYCLECOUNT: + LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS)); + break; + case PSXPC: + LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS)); + break; + case TARGET: + LWZ(HWRegisters[index].code, 0, GetHWRegSpecial(TARGETPTR)); + break; + default: + SysPrintf("Error: Unknown special register in GetHWRegSpecial()\n"); + break; + } + HWRegisters[index].usage &= ~HWUSAGE_RESERVED; + } + else if (DstCPUReg != -1) { + int dst = DstCPUReg; + DstCPUReg = -1; + + MoveHWRegToCPUReg(dst, index); + } + + return UpdateHWRegUsage(index, usage); +} + +static int PutHWRegSpecial(int which) +{ + int index = GetSpecialIndexFromHWRegs(which); + int usage = HWUSAGE_WRITE | HWUSAGE_SPECIAL; + + if (DstCPUReg != -1 && index != -1) { + if (HWRegisters[index].code != DstCPUReg) { + int tmp = DstCPUReg; + DstCPUReg = -1; + DisposeHWReg(index); + DstCPUReg = tmp; + } + } + switch (which) { + case PSXREGS: + case TARGETPTR: + SysPrintf("Error: Read-only special register in PutHWRegSpecial()\n"); + case REG_WZERO: + if (index >= 0) { + if (HWRegisters[index].usage & HWUSAGE_WRITE) + break; + } + index = MapRegSpecial(which); + HWRegisters[index].flush = NULL; + break; + default: + if (index == -1) { + usage |= HWUSAGE_INITED; + index = MapRegSpecial(which); + + HWRegisters[index].usage |= HWUSAGE_RESERVED; + switch (which) { + case ARG1: + case ARG2: + case ARG3: + MoveHWRegToCPUReg(3+(which-ARG1), index); + /*reg = GetHWRegFromCPUReg(3+(which-ARG1)); + + if (HWRegisters[reg].usage != HWUSAGE_NONE) { + HWRegisters[reg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG); + if (HWRegisters[reg].flush != NULL && HWRegisters[reg].usage & (HWUSAGE_WRITE | HWUSAGE_READ)) { + MR(HWRegisters[index].code, HWRegisters[reg].code); + } else { + FlushHWReg(reg); + } + } + HWRegisters[reg].code = HWRegisters[index].code; + if (!(HWRegisters[index].code >= 3 && HWRegisters[index].code <=31)) + SysPrintf("Error! Register allocation"); + HWRegisters[index].code = 3+(which-ARG1);*/ + HWRegisters[index].flush = NULL; + + usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG; + break; + } + } + HWRegisters[index].usage &= ~HWUSAGE_RESERVED; + break; + } + + DstCPUReg = -1; + + return UpdateHWRegUsage(index, usage); +} + +#pragma mark --- --- + +static void MapConst(int reg, u32 _const) { + if (reg == 0) + return; + if (IsConst(reg) && iRegs[reg].k == _const) + return; + + DisposeHWReg(iRegs[reg].reg); + iRegs[reg].k = _const; + iRegs[reg].state = ST_CONST; +} + +static void MapCopy(int dst, int src) +{ + // do it the lazy way for now + MR(PutHWReg32(dst), GetHWReg32(src)); +} + +static void iFlushReg(u32 nextpc, int reg) { + if (!IsMapped(reg) && IsConst(reg)) { + GetHWReg32(reg); + } + if (IsMapped(reg)) { + if (nextpc) { + int use = nextPsxRegUse(nextpc, reg); + if ((use & REGUSE_RW) == REGUSE_WRITE) { + DisposeHWReg(iRegs[reg].reg); + } else { + FlushHWReg(iRegs[reg].reg); + } + } else { + FlushHWReg(iRegs[reg].reg); + } + } +} + +static void iFlushRegs(u32 nextpc) { + int i; + + for (i=1; i<NUM_REGISTERS; i++) { + iFlushReg(nextpc, i); + } +} + +static void Return() +{ + iFlushRegs(0); + FlushAllHWReg(); + if (((u32)returnPC & 0x1fffffc) == (u32)returnPC) { + BA((u32)returnPC); + } + else { + LIW(0, (u32)returnPC); + MTLR(0); + BLR(); + } +} + +static void iRet() { + /* store cycle */ + count = (idlecyclecount + (pc - pcold) / 4) * BIAS; + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + Return(); +} + +static int iLoadTest() { + u32 tmp; + + // check for load delay + tmp = psxRegs.code >> 26; + switch (tmp) { + case 0x10: // COP0 + switch (_Rs_) { + case 0x00: // MFC0 + case 0x02: // CFC0 + return 1; + } + break; + case 0x12: // COP2 + switch (_Funct_) { + case 0x00: + switch (_Rs_) { + case 0x00: // MFC2 + case 0x02: // CFC2 + return 1; + } + break; + } + break; + case 0x32: // LWC2 + return 1; + default: + if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR + return 1; + } + break; + } + return 0; +} + +/* set a pending branch */ +static void SetBranch() { + int treg; + branch = 1; + psxRegs.code = PSXMu32(pc); + pc+=4; + + if (iLoadTest() == 1) { + iFlushRegs(0); + LIW(0, psxRegs.code); + STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); + /* store cycle */ + count = (idlecyclecount + (pc - pcold) / 4) * BIAS; + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + + treg = GetHWRegSpecial(TARGET); + MR(PutHWRegSpecial(ARG2), treg); + DisposeHWReg(GetHWRegFromCPUReg(treg)); + LIW(PutHWRegSpecial(ARG1), _Rt_); + LIW(GetHWRegSpecial(PSXPC), pc); + FlushAllHWReg(); + CALLFunc((u32)psxDelayTest); + + Return(); + return; + } + + recBSC[psxRegs.code>>26](); + + iFlushRegs(0); + treg = GetHWRegSpecial(TARGET); + MR(PutHWRegSpecial(PSXPC), GetHWRegSpecial(TARGET)); // FIXME: this line should not be needed + DisposeHWReg(GetHWRegFromCPUReg(treg)); + FlushAllHWReg(); + + count = (idlecyclecount + (pc - pcold) / 4) * BIAS; + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + FlushAllHWReg(); + CALLFunc((u32)psxBranchTest); + + // TODO: don't return if target is compiled + Return(); +} + +static void iJump(u32 branchPC) { + u32 *b1, *b2; + branch = 1; + psxRegs.code = PSXMu32(pc); + pc+=4; + + if (iLoadTest() == 1) { + iFlushRegs(0); + LIW(0, psxRegs.code); + STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); + /* store cycle */ + count = (idlecyclecount + (pc - pcold) / 4) * BIAS; + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + + LIW(PutHWRegSpecial(ARG2), branchPC); + LIW(PutHWRegSpecial(ARG1), _Rt_); + LIW(GetHWRegSpecial(PSXPC), pc); + FlushAllHWReg(); + CALLFunc((u32)psxDelayTest); + + Return(); + return; + } + + recBSC[psxRegs.code>>26](); + + iFlushRegs(branchPC); + LIW(PutHWRegSpecial(PSXPC), branchPC); + FlushAllHWReg(); + + count = (idlecyclecount + (pc - pcold) / 4) * BIAS; + //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) { + // LIW(PutHWRegSpecial(CYCLECOUNT), 0); + //} else { + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + //} + FlushAllHWReg(); + CALLFunc((u32)psxBranchTest); + + if (!Config.HLE && Config.PsxOut && + ((branchPC & 0x1fffff) == 0xa0 || + (branchPC & 0x1fffff) == 0xb0 || + (branchPC & 0x1fffff) == 0xc0)) + CALLFunc((u32)psxJumpTest); + + // always return for now... + //Return(); + + // maybe just happened an interruption, check so + LIW(0, branchPC); + CMPLW(GetHWRegSpecial(PSXPC), 0); + BNE_L(b1); + + LIW(3, PC_REC(branchPC)); + LWZ(3, 0, 3); + CMPLWI(3, 0); + BNE_L(b2); + + B_DST(b1); + Return(); + + // next bit is already compiled - jump right to it + B_DST(b2); + MTCTR(3); + BCTR(); +} + +static void iBranch(u32 branchPC, int savectx) { + HWRegister HWRegistersS[NUM_HW_REGISTERS]; + iRegisters iRegsS[NUM_REGISTERS]; + int HWRegUseCountS = 0; + u32 respold=0; + u32 *b1, *b2; + + if (savectx) { + respold = resp; + memcpy(iRegsS, iRegs, sizeof(iRegs)); + memcpy(HWRegistersS, HWRegisters, sizeof(HWRegisters)); + HWRegUseCountS = HWRegUseCount; + } + + branch = 1; + psxRegs.code = PSXMu32(pc); + + // the delay test is only made when the branch is taken + // savectx == 0 will mean that :) + if (savectx == 0 && iLoadTest() == 1) { + iFlushRegs(0); + LIW(0, psxRegs.code); + STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); + /* store cycle */ + count = (idlecyclecount + ((pc+4) - pcold) / 4) * BIAS; + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + + LIW(PutHWRegSpecial(ARG2), branchPC); + LIW(PutHWRegSpecial(ARG1), _Rt_); + LIW(GetHWRegSpecial(PSXPC), pc); + FlushAllHWReg(); + CALLFunc((u32)psxDelayTest); + + Return(); + return; + } + + pc+= 4; + recBSC[psxRegs.code>>26](); + + iFlushRegs(branchPC); + LIW(PutHWRegSpecial(PSXPC), branchPC); + FlushAllHWReg(); + + /* store cycle */ + count = (idlecyclecount + (pc - pcold) / 4) * BIAS; + //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) { + // LIW(PutHWRegSpecial(CYCLECOUNT), 0); + //} else { + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + //} + FlushAllHWReg(); + CALLFunc((u32)psxBranchTest); + + // always return for now... + //Return(); + + LIW(0, branchPC); + CMPLW(GetHWRegSpecial(PSXPC), 0); + BNE_L(b1); + + LIW(3, PC_REC(branchPC)); + LWZ(3, 0, 3); + CMPLWI(3, 0); + BNE_L(b2); + + B_DST(b1); + Return(); + + B_DST(b2); + MTCTR(3); + BCTR(); + + // maybe just happened an interruption, check so +/* CMP32ItoM((u32)&psxRegs.pc, branchPC); + j8Ptr[1] = JE8(0); + RET(); + + x86SetJ8(j8Ptr[1]); + MOV32MtoR(EAX, PC_REC(branchPC)); + TEST32RtoR(EAX, EAX); + j8Ptr[2] = JNE8(0); + RET(); + + x86SetJ8(j8Ptr[2]); + JMP32R(EAX);*/ + + pc-= 4; + if (savectx) { + resp = respold; + memcpy(iRegs, iRegsS, sizeof(iRegs)); + memcpy(HWRegisters, HWRegistersS, sizeof(HWRegisters)); + HWRegUseCount = HWRegUseCountS; + } +} + + +static void iDumpRegs() { + int i, j; + + printf("%lx %lx\n", psxRegs.pc, psxRegs.cycle); + for (i=0; i<4; i++) { + for (j=0; j<8; j++) + printf("%lx ", psxRegs.GPR.r[j*i]); + printf("\n"); + } +} + +void iDumpBlock(char *ptr) { +/* FILE *f; + u32 i; + + SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxCurrentCycle); + + for (i = psxRegs.pc; i < pc; i+=4) + SysPrintf("%s\n", disR3000AF(PSXMu32(i), i)); + + fflush(stdout); + f = fopen("dump1", "w"); + fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f); + fclose(f); + system("ndisasmw -u dump1"); + fflush(stdout);*/ +} + +#define REC_FUNC(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(0); \ + LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \ + STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \ + LIW(PutHWRegSpecial(PSXPC), (u32)pc); \ + FlushAllHWReg(); \ + CALLFunc((u32)psx##f); \ +/* branch = 2; */\ +} + +#define REC_SYS(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(0); \ + LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \ + STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \ + LIW(PutHWRegSpecial(PSXPC), (u32)pc); \ + FlushAllHWReg(); \ + CALLFunc((u32)psx##f); \ + branch = 2; \ + iRet(); \ +} + +#define REC_BRANCH(f) \ +void psx##f(); \ +static void rec##f() { \ + iFlushRegs(0); \ + LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \ + STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \ + LIW(PutHWRegSpecial(PSXPC), (u32)pc); \ + FlushAllHWReg(); \ + CALLFunc((u32)psx##f); \ + branch = 2; \ + iRet(); \ +} + +static void freeMem(int all) +{ + if (recMem) free(recMem); + if (recRAM) free(recRAM); + if (recROM) free(recROM); + recMem = recRAM = recROM = 0; + + if (all && psxRecLUT) { + free(psxRecLUT); psxRecLUT = NULL; + } +} + +static int allocMem() { + int i; + + freeMem(0); + + if (psxRecLUT==NULL) + psxRecLUT = (u32*) malloc(0x010000 * 4); + + recMem = (char*) malloc(RECMEM_SIZE); + //recMem = mmap(NULL, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); + recRAM = (char*) malloc(0x200000); + recROM = (char*) malloc(0x080000); + if (recRAM == NULL || recROM == NULL || recMem == NULL/*(void *)-1*/ || psxRecLUT == NULL) { + freeMem(1); + SysMessage("Error allocating memory"); return -1; + } + + for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16]; + memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * 4); + memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * 4); + + for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16]; + + return 0; +} + +static int recInit() { + return allocMem(); +} + +static void recReset() { + memset(recRAM, 0, 0x200000); + memset(recROM, 0, 0x080000); + + ppcInit(); + ppcSetPtr((u32 *)recMem); + + branch = 0; + memset(iRegs, 0, sizeof(iRegs)); + iRegs[0].state = ST_CONST; + iRegs[0].k = 0; +} + +static void recShutdown() { + freeMem(1); + ppcShutdown(); +} + +static void recError() { + SysReset(); + ClosePlugins(); + SysMessage("Unrecoverable error while running recompiler\n"); + SysRunGui(); +} + +__inline static void execute() { + void (**recFunc)(); + char *p; + + p = (char*)PC_REC(psxRegs.pc); + /*if (p != NULL)*/ recFunc = (void (**)()) (u32)p; + /*else { recError(); return; }*/ + + if (*recFunc == 0) { + recRecompile(); + } + recRun(*recFunc, (u32)&psxRegs, (u32)&psxM); +} + +static void recExecute() { + for (;;) execute(); +} + +static void recExecuteBlock() { + execute(); +} + +static void recClear(u32 Addr, u32 Size) { + memset((void*)PC_REC(Addr), 0, Size * 4); +} + +static void recNULL() { +// SysMessage("recUNK: %8.8x\n", psxRegs.code); +} + +/********************************************************* +* goes to opcodes tables... * +* Format: table[something....] * +*********************************************************/ + +//REC_SYS(SPECIAL); +static void recSPECIAL() { + recSPC[_Funct_](); +} + +static void recREGIMM() { + recREG[_Rt_](); +} + +static void recCOP0() { + recCP0[_Rs_](); +} + +//REC_SYS(COP2); +static void recCOP2() { + recCP2[_Funct_](); +} + +static void recBASIC() { + recCP2BSC[_Rs_](); +} + +//end of Tables opcodes... + +#pragma mark - Arithmetic with immediate operand - +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +#if 0 +/*REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); +REC_FUNC(SLTI); +REC_FUNC(SLTIU);*/ +#else +static void recADDIU() { +// Rt = Rs + Im + if (!_Rt_) return; + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k + _Imm_); + } else { + if (_Imm_ == 0) { + MapCopy(_Rt_, _Rs_); + } else { + ADDI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _Imm_); + } + } +} + +static void recADDI() { +// Rt = Rs + Im + recADDIU(); +} + +//REC_FUNC(SLTI); +//REC_FUNC(SLTIU); +//CR0: SIGN | POSITIVE | ZERO | SOVERFLOW | SOVERFLOW | OVERFLOW | CARRY +static void recSLTI() { +// Rt = Rs < Im (signed) + if (!_Rt_) return; + + if (IsConst(_Rs_)) { + MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_); + } else { + if (_Imm_ == 0) { + SRWI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), 31); + } else { + int reg; + CMPWI(GetHWReg32(_Rs_), _Imm_); + reg = PutHWReg32(_Rt_); + LI(reg, 1); + BLT(1); + LI(reg, 0); + } + } +} + +static void recSLTIU() { +// Rt = Rs < Im (unsigned) + if (!_Rt_) return; + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_); + } else { + int reg; + CMPLWI(GetHWReg32(_Rs_), _Imm_); + reg = PutHWReg32(_Rt_); + LI(reg, 1); + BLT(1); + LI(reg, 0); + } +} + +static void recANDI() { +// Rt = Rs And Im + if (!_Rt_) return; + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_); + } else { + ANDI_(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_); + } +} + +static void recORI() { +// Rt = Rs Or Im + if (!_Rt_) return; + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_); + } else { + if (_Imm_ == 0) { + MapCopy(_Rt_, _Rs_); + } else { + ORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_); + } + } +} + +static void recXORI() { +// Rt = Rs Xor Im + if (!_Rt_) return; + + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_); + } else { + XORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_); + } +} +#endif +//end of * Arithmetic with immediate operand + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +//REC_FUNC(LUI); +//#if 0*/ +static void recLUI() { +// Rt = Imm << 16 + if (!_Rt_) return; + + MapConst(_Rt_, psxRegs.code << 16); +} +//#endif +//End of Load Higher ..... + +#pragma mark - Register arithmetic - +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +#if 0 +/*REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU);*/ +#else +static void recADDU() { +// Rd = Rs + Rt + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k); + } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) { + ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), (s16)iRegs[_Rs_].k); + } else if ((iRegs[_Rs_].k & 0xffff) == 0) { + ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k>>16); + } else { + ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) { + ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), (s16)iRegs[_Rt_].k); + } else if ((iRegs[_Rt_].k & 0xffff) == 0) { + ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k>>16); + } else { + ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else { + ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } +} + +static void recADD() { +// Rd = Rs + Rt + recADDU(); +} + +static void recSUBU() { +// Rd = Rs - Rt + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k); + } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((s32)(s16)(-iRegs[_Rt_].k) == (s32)(-iRegs[_Rt_].k)) { + ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), -iRegs[_Rt_].k); + } else if (((-iRegs[_Rt_].k) & 0xffff) == 0) { + ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rs_), (-iRegs[_Rt_].k)>>16); + } else { + SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else { + SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } +} + +static void recSUB() { +// Rd = Rs - Rt + recSUBU(); +} + +static void recAND() { +// Rd = Rs And Rt + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k); + } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + // TODO: implement shifted (ANDIS) versions of these + if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) { + ANDI_(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) { + ANDI_(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k); + } else { + AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else { + AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } +} + +static void recOR() { +// Rd = Rs Or Rt + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k); + } + else { + if (_Rs_ == _Rt_) { + MapCopy(_Rd_, _Rs_); + } + else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) { + ORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) { + ORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k); + } else { + OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else { + OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } +} + +static void recXOR() { +// Rd = Rs Xor Rt + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k); + } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) { + XORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) { + XORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k); + } else { + XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else { + XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } +} + +static void recNOR() { +// Rd = Rs Nor Rt + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k)); + } /*else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) { + NORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) { + NORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k); + } else { + NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } */else { + NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } +} + +static void recSLT() { +// Rd = Rs < Rt (signed) + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k); + } else { // TODO: add immidiate cases + int reg; + CMPW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + reg = PutHWReg32(_Rd_); + LI(reg, 1); + BLT(1); + LI(reg, 0); + } +} + +static void recSLTU() { +// Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k); + } else { // TODO: add immidiate cases + SUBFC(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_)); + SUBFE(PutHWReg32(_Rd_), GetHWReg32(_Rd_), GetHWReg32(_Rd_)); + NEG(PutHWReg32(_Rd_), GetHWReg32(_Rd_)); + } +} +#endif +//End of * Register arithmetic + +#pragma mark - mult/div & Register trap logic - +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +#if 0 +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC(DIV); +REC_FUNC(DIVU); +#else + +int DoShift(u32 k) +{ + u32 i; + for (i=0; i<30; i++) { + if (k == (1ul << i)) + return i; + } + return -1; +} + +//REC_FUNC(MULT); + +// FIXME: doesn't work in GT - wrong way marker +static void recMULT() { +// Lo/Hi = Rs * Rt (signed) + s32 k; int r; + int usehi, uselo; + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || + (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { + MapConst(REG_LO, 0); + MapConst(REG_HI, 0); + return; + } + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + u64 res = (s64)((s64)(s32)iRegs[_Rs_].k * (s64)(s32)iRegs[_Rt_].k); + MapConst(REG_LO, (res & 0xffffffff)); + MapConst(REG_HI, ((res >> 32) & 0xffffffff)); + return; + } + + if (IsConst(_Rs_)) { + k = (s32)iRegs[_Rs_].k; + r = _Rt_; + } else if (IsConst(_Rt_)) { + k = (s32)iRegs[_Rt_].k; + r = _Rs_; + } else { + r = -1; + k = 0; + } + + // FIXME: this should not be needed!!! +// uselo = isPsxRegUsed(pc, REG_LO); +// usehi = isPsxRegUsed(pc, REG_HI); + uselo = 1; //isPsxRegUsed(pc, REG_LO); + usehi = 1; //isPsxRegUsed(pc, REG_HI); + + + if (r != -1) { + int shift = DoShift(k); + if (shift != -1) { + if (uselo) { + SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift) + } + if (usehi) { + SRAWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift); + } + } else { + //if ((s32)(s16)k == k) { + // MULLWI(PutHWReg32(REG_LO), GetHWReg32(r), k); + // MULHWI(PutHWReg32(REG_HI), GetHWReg32(r), k); + //} else + { + if (uselo) { + MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + if (usehi) { + MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + } + } else { + if (uselo) { + MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + if (usehi) { + MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } +} + +static void recMULTU() { +// Lo/Hi = Rs * Rt (unsigned) + u32 k; int r; + int usehi, uselo; + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || + (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { + MapConst(REG_LO, 0); + MapConst(REG_HI, 0); + return; + } + + if (IsConst(_Rs_) && IsConst(_Rt_)) { + u64 res = (u64)((u64)(u32)iRegs[_Rs_].k * (u64)(u32)iRegs[_Rt_].k); + MapConst(REG_LO, (res & 0xffffffff)); + MapConst(REG_HI, ((res >> 32) & 0xffffffff)); + return; + } + + if (IsConst(_Rs_)) { + k = (s32)iRegs[_Rs_].k; + r = _Rt_; + } else if (IsConst(_Rt_)) { + k = (s32)iRegs[_Rt_].k; + r = _Rs_; + } else { + r = -1; + k = 0; + } + + uselo = isPsxRegUsed(pc, REG_LO); + usehi = isPsxRegUsed(pc, REG_HI); + + if (r != -1) { + int shift = DoShift(k); + if (shift != -1) { + if (uselo) { + SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift); + } + if (usehi) { + SRWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift); + } + } else { + { + if (uselo) { + MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + if (usehi) { + MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + } + } else { + if (uselo) { + MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + if (usehi) { + MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } +} + +static void recDIV() { +// Lo/Hi = Rs / Rt (signed) + int usehi; + + if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) { + MapConst(REG_LO, 0); + MapConst(REG_HI, 0); + return; + } + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(REG_LO, (s32)iRegs[_Rs_].k / (s32)iRegs[_Rt_].k); + MapConst(REG_HI, (s32)iRegs[_Rs_].k % (s32)iRegs[_Rt_].k); + return; + } + + usehi = isPsxRegUsed(pc, REG_HI); + + if (IsConst(_Rt_)) { + int shift = DoShift(iRegs[_Rt_].k); + if (shift != -1) { + SRAWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift); + ADDZE(PutHWReg32(REG_LO), GetHWReg32(REG_LO)); + if (usehi) { + RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31); + } + } else if (iRegs[_Rt_].k == 3) { + // http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html + LIS(PutHWReg32(REG_HI), 0x5555); + ADDI(PutHWReg32(REG_HI), GetHWReg32(REG_HI), 0x5556); + MULHW(PutHWReg32(REG_LO), GetHWReg32(REG_HI), GetHWReg32(_Rs_)); + SRWI(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 31); + ADD(PutHWReg32(REG_LO), GetHWReg32(REG_LO), GetHWReg32(REG_HI)); + if (usehi) { + MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), 3); + SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI)); + } + } else { + DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + if (usehi) { + if ((iRegs[_Rt_].k & 0x7fff) == iRegs[_Rt_].k) { + MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), iRegs[_Rt_].k); + } else { + MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_)); + } + SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI)); + } + } + } else { + DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + if (usehi) { + MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_)); + SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI)); + } + } +} + +static void recDIVU() { +// Lo/Hi = Rs / Rt (unsigned) + int usehi; + + if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) { + MapConst(REG_LO, 0); + MapConst(REG_HI, 0); + return; + } + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(REG_LO, (u32)iRegs[_Rs_].k / (u32)iRegs[_Rt_].k); + MapConst(REG_HI, (u32)iRegs[_Rs_].k % (u32)iRegs[_Rt_].k); + return; + } + + usehi = isPsxRegUsed(pc, REG_HI); + + if (IsConst(_Rt_)) { + int shift = DoShift(iRegs[_Rt_].k); + if (shift != -1) { + SRWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift); + if (usehi) { + RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31); + } + } else { + DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + if (usehi) { + MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO)); + SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI)); + } + } + } else { + DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + if (usehi) { + MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO)); + SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI)); + } + } +} +#endif +//End of * Register mult/div & Register trap logic + +#pragma mark - memory access - + +#if 0 +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); + +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); +#else +static void preMemRead() +{ + int rs; + + ReserveArgs(1); + if (_Rs_ != _Rt_) { + DisposeHWReg(iRegs[_Rt_].reg); + } + rs = GetHWReg32(_Rs_); + if (rs != 3 || _Imm_ != 0) { + ADDI(PutHWRegSpecial(ARG1), rs, _Imm_); + } + if (_Rs_ == _Rt_) { + DisposeHWReg(iRegs[_Rt_].reg); + } + InvalidateCPURegs(); + //FlushAllHWReg(); +} + +static void preMemWrite(int size) +{ + int rs; + + ReserveArgs(2); + rs = GetHWReg32(_Rs_); + if (rs != 3 || _Imm_ != 0) { + ADDI(PutHWRegSpecial(ARG1), rs, _Imm_); + } + if (size == 1) { + RLWINM(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0, 24, 31); + //ANDI_(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0xff); + } else if (size == 2) { + RLWINM(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0, 16, 31); + //ANDI_(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0xffff); + } else { + MR(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_)); + } + + InvalidateCPURegs(); + //FlushAllHWReg(); +} + +static void recLB() { +// Rt = mem[Rs + Im] (signed) + + /*if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRs8(addr)); + return; + } + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (!_Rt_) return; + + addr = (u32)&psxM[addr & 0x1fffff]; + LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct? + LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_)); + EXTSB(PutHWReg32(_Rt_), GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + + addr = (u32)&psxH[addr & 0xfff]; + LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct? + LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_)); + EXTSB(PutHWReg32(_Rt_), GetHWReg32(_Rt_)); + return; + } + // SysPrintf("unhandled r8 %x\n", addr); + }*/ + + preMemRead(); + CALLFunc((u32)psxMemRead8); + if (_Rt_) { + EXTSB(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL)); + DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL)); + } +} + +static void recLBU() { +// Rt = mem[Rs + Im] (unsigned) + + /*if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu8(addr)); + return; + } + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (!_Rt_) return; + + addr = (u32)&psxM[addr & 0x1fffff]; + LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct? + LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + + addr = (u32)&psxH[addr & 0xfff]; + LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct? + LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_)); + return; + } + // SysPrintf("unhandled r8 %x\n", addr); + }*/ + + preMemRead(); + CALLFunc((u32)psxMemRead8); + + if (_Rt_) { + SetDstCPUReg(3); + PutHWReg32(_Rt_); + } +} + +static void recLH() { +// Rt = mem[Rs + Im] (signed) + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRs16(addr)); + return; + } + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]); + LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]); + LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_)); + return; + } + // SysPrintf("unhandled r16 %x\n", addr); + } + + preMemRead(); + CALLFunc((u32)psxMemRead16); + if (_Rt_) { + EXTSH(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL)); + DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL)); + } +} + +static void recLHU() { +// Rt = mem[Rs + Im] (unsigned) + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu16(addr)); + return; + } + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]); + LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]); + LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80) { + if (addr >= 0x1f801c00 && addr < 0x1f801e00) { + if (!_Rt_) return; + + ReserveArgs(1); + LIW(PutHWRegSpecial(ARG1), addr); + DisposeHWReg(iRegs[_Rt_].reg); + InvalidateCPURegs(); + CALLFunc((u32)SPU_readRegister); + + SetDstCPUReg(3); + PutHWReg32(_Rt_); + return; + } + switch (addr) { + case 0x1f801100: case 0x1f801110: case 0x1f801120: + if (!_Rt_) return; + + ReserveArgs(1); + LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3); + DisposeHWReg(iRegs[_Rt_].reg); + InvalidateCPURegs(); + CALLFunc((u32)psxRcntRcount); + + SetDstCPUReg(3); + PutHWReg32(_Rt_); + return; + + case 0x1f801104: case 0x1f801114: case 0x1f801124: + if (!_Rt_) return; + + ReserveArgs(1); + LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3); + DisposeHWReg(iRegs[_Rt_].reg); + InvalidateCPURegs(); + CALLFunc((u32)psxRcntRmode); + + SetDstCPUReg(3); + PutHWReg32(_Rt_); + return; + + case 0x1f801108: case 0x1f801118: case 0x1f801128: + if (!_Rt_) return; + + ReserveArgs(1); + LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3); + DisposeHWReg(iRegs[_Rt_].reg); + InvalidateCPURegs(); + CALLFunc((u32)psxRcntRtarget); + + SetDstCPUReg(3); + PutHWReg32(_Rt_); + return; + } + } + // SysPrintf("unhandled r16u %x\n", addr); + } + + preMemRead(); + CALLFunc((u32)psxMemRead16); + if (_Rt_) { + SetDstCPUReg(3); + PutHWReg32(_Rt_); + } +} + +static void recLW() { +// Rt = mem[Rs + Im] (unsigned) + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + if (!_Rt_) return; + // since bios is readonly it won't change + MapConst(_Rt_, psxRu32(addr)); + return; + } + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]); + LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]); + LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + return; + } + if (t == 0x1f80) { + switch (addr) { + case 0x1f801080: case 0x1f801084: case 0x1f801088: + case 0x1f801090: case 0x1f801094: case 0x1f801098: + case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8: + case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8: + case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8: + case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8: + case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8: + case 0x1f801070: case 0x1f801074: + case 0x1f8010f0: case 0x1f8010f4: + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xffff]); + LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + return; + + case 0x1f801810: + if (!_Rt_) return; + + DisposeHWReg(iRegs[_Rt_].reg); + InvalidateCPURegs(); + CALLFunc((u32)GPU_readData); + + SetDstCPUReg(3); + PutHWReg32(_Rt_); + return; + + case 0x1f801814: + if (!_Rt_) return; + + DisposeHWReg(iRegs[_Rt_].reg); + InvalidateCPURegs(); + CALLFunc((u32)GPU_readStatus); + + SetDstCPUReg(3); + PutHWReg32(_Rt_); + return; + } + } +// SysPrintf("unhandled r32 %x\n", addr); + } + + preMemRead(); + CALLFunc((u32)psxMemRead32); + if (_Rt_) { + SetDstCPUReg(3); + PutHWReg32(_Rt_); + } +} + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); +/*extern u32 LWL_MASK[4]; +extern u32 LWL_SHIFT[4]; + +void iLWLk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32ItoR(ECX, LWL_MASK[shift]); + SHL32ItoR(EAX, LWL_SHIFT[shift]); + OR32RtoR (EAX, ECX); +} + +void recLWL() { +// Rt = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iLWLk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iLWLk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + CALLFunc((u32)psxMemRead32); + + if (_Rt_) { + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)LWL_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift] + + MOV32ItoR(ECX, (u32)LWL_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift] + + OR32RtoR(EAX, EDX); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } else { +// ADD32ItoR(ESP, 8); + resp+= 8; + } +} + +static void recLWBlock(int count) { + u32 *code = PSXM(pc); + int i, respsave; +// Rt = mem[Rs + Im] (unsigned) + +// iFlushRegs(0); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0xfff0) == 0xbfc0) { + // since bios is readonly it won't change + for (i=0; i<count; i++, code++, addr+=4) { + if (_fRt_(*code)) { + MapConst(_fRt_(*code), psxRu32(addr)); + } + } + return; + } + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + for (i=0; i<count; i++, code++, addr+=4) { + if (!_fRt_(*code)) return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + for (i=0; i<count; i++, code++, addr+=4) { + if (!_fRt_(*code)) return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + } + + SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_)); + iPushOfB(); + CALLFunc((u32)psxMemPointer); +// ADD32ItoR(ESP, 4); + resp+= 4; + + respsave = resp; resp = 0; + TEST32RtoR(EAX, EAX); + j32Ptr[4] = JZ32(0); + XOR32RtoR(ECX, ECX); + for (i=0; i<count; i++, code++) { + if (_fRt_(*code)) { + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32RmStoR(EDX, EAX, ECX, 2); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX); + } + if (i != (count-1)) INC32R(ECX); + } + j32Ptr[5] = JMP32(0); + x86SetJ32(j32Ptr[4]); + for (i=0, code = PSXM(pc); i<count; i++, code++) { + psxRegs.code = *code; + recLW(); + } + ADD32ItoR(ESP, resp); + x86SetJ32(j32Ptr[5]); + resp = respsave; +} + +extern u32 LWR_MASK[4]; +extern u32 LWR_SHIFT[4]; + +void iLWRk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32ItoR(ECX, LWR_MASK[shift]); + SHR32ItoR(EAX, LWR_SHIFT[shift]); + OR32RtoR (EAX, ECX); +} + +void recLWR() { +// Rt = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iLWRk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iLWRk(addr & 3); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + CALLFunc((u32)psxMemRead32); + + if (_Rt_) { + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)LWR_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift] + + MOV32ItoR(ECX, (u32)LWR_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift] + + OR32RtoR(EAX, EDX); + + iRegs[_Rt_].state = ST_UNK; + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } else { +// ADD32ItoR(ESP, 8); + resp+= 8; + } +}*/ + +static void recSB() { +// mem[Rs + Im] = Rt + + /*if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k); + } else { + MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k); + } else { + MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV8RtoM((u32)&psxH[addr & 0xfff], EAX); + } + return; + } +// SysPrintf("unhandled w8 %x\n", addr); + }*/ + + preMemWrite(1); + CALLFunc((u32)psxMemWrite8); +} + +static void recSH() { +// mem[Rs + Im] = Rt + + /*if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + if (IsConst(_Rt_)) { + MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k); + } else { + MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + if (IsConst(_Rt_)) { + MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k); + } else { + MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV16RtoM((u32)&psxH[addr & 0xfff], EAX); + } + return; + } + if (t == 0x1f80) { + if (addr >= 0x1f801c00 && addr < 0x1f801e00) { + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + PUSH32I (addr); + CALL32M ((u32)&SPU_writeRegister); +#ifndef __WIN32__ + resp+= 8; +#endif + return; + } + } +// SysPrintf("unhandled w16 %x\n", addr); + }*/ + + preMemWrite(2); + CALLFunc((u32)psxMemWrite16); +} + +static void recSW() { +// mem[Rs + Im] = Rt + u32 *b1, *b2; +#if 0 + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + LIW(0, addr & 0x1fffff); + STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + LIW(0, (u32)&psxH[addr & 0xfff]); + STWBRX(GetHWReg32(_Rt_), 0, 0); + return; + } + if (t == 0x1f80) { + switch (addr) { + case 0x1f801080: case 0x1f801084: + case 0x1f801090: case 0x1f801094: + case 0x1f8010a0: case 0x1f8010a4: + case 0x1f8010b0: case 0x1f8010b4: + case 0x1f8010c0: case 0x1f8010c4: + case 0x1f8010d0: case 0x1f8010d4: + case 0x1f8010e0: case 0x1f8010e4: + case 0x1f801074: + case 0x1f8010f0: + LIW(0, (u32)&psxH[addr & 0xffff]); + STWBRX(GetHWReg32(_Rt_), 0, 0); + return; + +/* case 0x1f801810: + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + CALL32M((u32)&GPU_writeData); +#ifndef __WIN32__ + resp+= 4; +#endif + return; + + case 0x1f801814: + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + CALL32M((u32)&GPU_writeStatus); +#ifndef __WIN32__ + resp+= 4; +#endif*/ + } + } +// SysPrintf("unhandled w32 %x\n", addr); + } + +/* LIS(0, 0x0079 + ((_Imm_ <= 0) ? 1 : 0)); + CMPLW(GetHWReg32(_Rs_), 0); + BGE_L(b1); + + //SaveContext(); + ADDI(0, GetHWReg32(_Rs_), _Imm_); + RLWINM(0, GetHWReg32(_Rs_), 0, 11, 31); + STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0); + B_L(b2); + + B_DST(b1);*/ +#endif + preMemWrite(4); + CALLFunc((u32)psxMemWrite32); + + //B_DST(b2); +} + +/* +static void recSWBlock(int count) { + u32 *code; + int i, respsave; +// mem[Rs + Im] = Rt + +// iFlushRegs(); + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + code = PSXM(pc); + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + for (i=0; i<count; i++, code++, addr+=4) { + if (IsConst(_fRt_(*code))) { + MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]); + MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX); + } + } + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + for (i=0; i<count; i++, code++, addr+=4) { + if (!_fRt_(*code)) return; + iRegs[_fRt_(*code)].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX); + } + return; + } + } + + SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_)); + iPushOfB(); + CALLFunc((u32)psxMemPointer); +// ADD32ItoR(ESP, 4); + resp+= 4; + + respsave = resp; resp = 0; + TEST32RtoR(EAX, EAX); + j32Ptr[4] = JZ32(0); + XOR32RtoR(ECX, ECX); + for (i=0, code = PSXM(pc); i<count; i++, code++) { + if (IsConst(_fRt_(*code))) { + MOV32ItoR(EDX, iRegs[_fRt_(*code)].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]); + } + MOV32RtoRmS(EAX, ECX, 2, EDX); + if (i != (count-1)) INC32R(ECX); + } + j32Ptr[5] = JMP32(0); + x86SetJ32(j32Ptr[4]); + for (i=0, code = PSXM(pc); i<count; i++, code++) { + psxRegs.code = *code; + recSW(); + } + ADD32ItoR(ESP, resp); + x86SetJ32(j32Ptr[5]); + resp = respsave; +} + +extern u32 SWL_MASK[4]; +extern u32 SWL_SHIFT[4]; + +void iSWLk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHR32ItoR(ECX, SWL_SHIFT[shift]); + AND32ItoR(EAX, SWL_MASK[shift]); + OR32RtoR (EAX, ECX); +} + +void recSWL() { +// mem[Rs + Im] = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iSWLk(addr & 3); + MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iSWLk(addr & 3); + MOV32RtoM((u32)&psxH[addr & 0xffc], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemRead32); + + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)SWL_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift] + + MOV32ItoR(ECX, (u32)SWL_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift] + + OR32RtoR (EAX, EDX); + PUSH32R (EAX); + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp+= 8; +} + +extern u32 SWR_MASK[4]; +extern u32 SWR_SHIFT[4]; + +void iSWRk(u32 shift) { + if (IsConst(_Rt_)) { + MOV32ItoR(ECX, iRegs[_Rt_].k); + } else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHL32ItoR(ECX, SWR_SHIFT[shift]); + AND32ItoR(EAX, SWR_MASK[shift]); + OR32RtoR (EAX, ECX); +} + +void recSWR() { +// mem[Rs + Im] = Rt Merge mem[Rs + Im] + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]); + iSWRk(addr & 3); + MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]); + iSWRk(addr & 3); + MOV32RtoM((u32)&psxH[addr & 0xffc], EAX); + return; + } + } + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + PUSH32R (EAX); + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemRead32); + + ADD32ItoR(ESP, 4); + POP32R (EDX); + AND32ItoR(EDX, 0x3); // shift = addr & 3; + + MOV32ItoR(ECX, (u32)SWR_MASK); + MOV32RmStoR(ECX, ECX, EDX, 2); + AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift] + + MOV32ItoR(ECX, (u32)SWR_SHIFT); + MOV32RmStoR(ECX, ECX, EDX, 2); + if (IsConst(_Rt_)) { + MOV32ItoR(EDX, iRegs[_Rt_].k); + } else { + MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]); + } + SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift] + + OR32RtoR (EAX, EDX); + PUSH32R (EAX); + + if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); + else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + } + AND32ItoR(EAX, ~3); + PUSH32R (EAX); + + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp+= 8; +}*/ +#endif + +#if 0 +/*REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA);*/ +#else +static void recSLL() { +// Rd = Rt << Sa + if (!_Rd_) return; + + if (IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rt_].k << _Sa_); + } else { + SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_); + } +} + +static void recSRL() { +// Rd = Rt >> Sa + if (!_Rd_) return; + + if (IsConst(_Rt_)) { + MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_); + } else { + SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_); + } +} + +static void recSRA() { +// Rd = Rt >> Sa + if (!_Rd_) return; + + if (IsConst(_Rt_)) { + MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_); + } else { + SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_); + } +} +#endif + +#pragma mark - shift ops - +#if 0 +/*REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV);*/ +#else +static void recSLLV() { +// Rd = Rt << Rs + if (!_Rd_) return; + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k); + } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + SLW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_)); + } +} + +static void recSRLV() { +// Rd = Rt >> Rs + if (!_Rd_) return; + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k); + } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + SRW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_)); + } +} + +static void recSRAV() { +// Rd = Rt >> Rs + if (!_Rd_) return; + + if (IsConst(_Rt_) && IsConst(_Rs_)) { + MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k); + } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k); + } else { + SRAW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_)); + } +} +#endif + +//REC_SYS(SYSCALL); +//REC_SYS(BREAK); + +//#if 0*/ +/*int dump;*/ +static void recSYSCALL() { +// dump=1; + iFlushRegs(0); + + ReserveArgs(2); + LIW(PutHWRegSpecial(PSXPC), pc - 4); + LIW(PutHWRegSpecial(ARG1), 0x20); + LIW(PutHWRegSpecial(ARG2), (branch == 1 ? 1 : 0)); + FlushAllHWReg(); + CALLFunc ((u32)psxException); + + branch = 2; + iRet(); +} + +static void recBREAK() { +} +//#endif + +#if 0 +/*REC_FUNC(MFHI); +REC_FUNC(MTHI); +REC_FUNC(MFLO); +REC_FUNC(MTLO);*/ +#else +static void recMFHI() { +// Rd = Hi + if (!_Rd_) return; + + if (IsConst(REG_HI)) { + MapConst(_Rd_, iRegs[REG_HI].k); + } else { + MapCopy(_Rd_, REG_HI); + } +} + +static void recMTHI() { +// Hi = Rs + + if (IsConst(_Rs_)) { + MapConst(REG_HI, iRegs[_Rs_].k); + } else { + MapCopy(REG_HI, _Rs_); + } +} + +static void recMFLO() { +// Rd = Lo + if (!_Rd_) return; + + if (IsConst(REG_LO)) { + MapConst(_Rd_, iRegs[REG_LO].k); + } else { + MapCopy(_Rd_, REG_LO); + } +} + +static void recMTLO() { +// Lo = Rs + + if (IsConst(_Rs_)) { + MapConst(REG_LO, iRegs[_Rs_].k); + } else { + MapCopy(REG_LO, _Rs_); + } +} +#endif + +#pragma mark - branch ops - +#if 0 +/*REC_BRANCH(J); +REC_BRANCH(JR); +REC_BRANCH(JAL); +REC_BRANCH(JALR); +REC_BRANCH(BLTZ); +REC_BRANCH(BGTZ); +REC_BRANCH(BLTZAL); +REC_BRANCH(BGEZAL); +REC_BRANCH(BNE); +REC_BRANCH(BEQ); +REC_BRANCH(BLEZ); +REC_BRANCH(BGEZ);*/ +#else +static void recBLTZ() { +// Branch if Rs < 0 + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k < 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMPWI(GetHWReg32(_Rs_), 0); + BLT_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBGTZ() { +// Branch if Rs > 0 + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k > 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMPWI(GetHWReg32(_Rs_), 0); + BGT_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBLTZAL() { +// Branch if Rs < 0 + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k < 0) { + MapConst(31, pc + 4); + + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMPWI(GetHWReg32(_Rs_), 0); + BLT_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + MapConst(31, pc + 4); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBGEZAL() { +// Branch if Rs >= 0 + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k >= 0) { + MapConst(31, pc + 4); + + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMPWI(GetHWReg32(_Rs_), 0); + BGE_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + MapConst(31, pc + 4); + + iBranch(bpc, 0); + pc+=4; +} + +static void recJ() { +// j target + + iJump(_Target_ * 4 + (pc & 0xf0000000)); +} + +static void recJAL() { +// jal target + MapConst(31, pc + 4); + + iJump(_Target_ * 4 + (pc & 0xf0000000)); +} + +static void recJR() { +// jr Rs + + if (IsConst(_Rs_)) { + iJump(iRegs[_Rs_].k); + //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k); + } else { + MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_)); + SetBranch(); + } +} + +static void recJALR() { +// jalr Rs + + if (_Rd_) { + MapConst(_Rd_, pc + 4); + } + + if (IsConst(_Rs_)) { + iJump(iRegs[_Rs_].k); + //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k); + } else { + MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_)); + SetBranch(); + } +} + +static void recBEQ() { +// Branch if Rs == Rt + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (_Rs_ == _Rt_) { + iJump(bpc); + } + else { + if (IsConst(_Rs_) && IsConst(_Rt_)) { + if (iRegs[_Rs_].k == iRegs[_Rt_].k) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) { + CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k); + } + else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) { + CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k); + } + else { + CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) { + CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k); + } + else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) { + CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k); + } + else { + CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + else { + CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + + BEQ_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + iBranch(bpc, 0); + pc+=4; + } +} + +static void recBNE() { +// Branch if Rs != Rt + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (_Rs_ == _Rt_) { + iJump(pc+4); + } + else { + if (IsConst(_Rs_) && IsConst(_Rt_)) { + if (iRegs[_Rs_].k != iRegs[_Rt_].k) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + else if (IsConst(_Rs_) && !IsMapped(_Rs_)) { + if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) { + CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k); + } + else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) { + CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k); + } + else { + CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + else if (IsConst(_Rt_) && !IsMapped(_Rt_)) { + if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) { + CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k); + } + else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) { + CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k); + } + else { + CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + } + else { + CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_)); + } + + BNE_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + iBranch(bpc, 0); + pc+=4; + } +} + +static void recBLEZ() { +// Branch if Rs <= 0 + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k <= 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMPWI(GetHWReg32(_Rs_), 0); + BLE_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + iBranch(bpc, 0); + pc+=4; +} + +static void recBGEZ() { +// Branch if Rs >= 0 + u32 bpc = _Imm_ * 4 + pc; + u32 *b; + + if (IsConst(_Rs_)) { + if ((s32)iRegs[_Rs_].k >= 0) { + iJump(bpc); return; + } else { + iJump(pc+4); return; + } + } + + CMPWI(GetHWReg32(_Rs_), 0); + BGE_L(b); + + iBranch(pc+4, 1); + + B_DST(b); + + iBranch(bpc, 0); + pc+=4; +} +#endif + +#if 1 +//REC_FUNC(MFC0); +//REC_SYS(MTC0); +//REC_FUNC(CFC0); +//REC_SYS(CTC0); +REC_FUNC(RFE); +//#else +static void recMFC0() { +// Rt = Cop0->Rd + if (!_Rt_) return; + + LWZ(PutHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS)); +} + +static void recCFC0() { +// Rt = Cop0->Rd + + recMFC0(); +} + +static void recMTC0() { +// Cop0->Rd = Rt + + /*if (IsConst(_Rt_)) { + switch (_Rd_) { + case 12: + MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); + break; + case 13: + MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00)); + break; + default: + MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); + break; + } + } else*/ { + switch (_Rd_) { + case 13: + RLWINM(0,GetHWReg32(_Rt_),0,22,15); // & ~(0xfc00) + STW(0, OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS)); + break; + default: + STW(GetHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS)); + break; + } + } + + if (_Rd_ == 12 || _Rd_ == 13) { + iFlushRegs(0); + LIW(PutHWRegSpecial(PSXPC), (u32)pc); + FlushAllHWReg(); + CALLFunc((u32)psxTestSWInts); + if(_Rd_ == 12) { + LWZ(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS)); + ORIS(0, 0, 0x8000); + STW(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS)); + } + branch = 2; + iRet(); + } +} + +static void recCTC0() { +// Cop0->Rd = Rt + + recMTC0(); +} +#else +static void recRFE() { + // TODO: implement multiple temp registers or cop0 registers + RLWINM(t1,Status,0,0,27); + RLWINM(Status,Status,30,28,31); + OR(Status,t1,Status); + + MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status); + MOV32RtoR(ECX, EAX); + AND32ItoR(EAX, 0xfffffff0); + AND32ItoR(ECX, 0x3c); + SHR32ItoR(ECX, 2); + OR32RtoR (EAX, ECX); + MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX); + CALLFunc((u32)psxExceptionTest); +} +#endif + +#if 0 +#define CP2_FUNC(f) \ +void gte##f(); \ +static void rec##f() { \ + iFlushRegs(0); \ + LIW(0, (u32)psxRegs.code); \ + STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \ + FlushAllHWReg(); \ + CALLFunc ((u32)gte##f); \ +} +CP2_FUNC(LWC2); +CP2_FUNC(SWC2); + +#else +#include "pGte.h" +#endif +// + +static void recHLE() { + iFlushRegs(0); + FlushAllHWReg(); + + if ((psxRegs.code & 0x3ffffff) == (psxRegs.code & 0x7)) { + CALLFunc((u32)psxHLEt[psxRegs.code & 0x7]); + } else { + // somebody else must have written to current opcode for this to happen!!!! + CALLFunc((u32)psxHLEt[0]); // call dummy function + } + + count = (idlecyclecount + (pc - pcold) / 4 + 20) * BIAS; + ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count); + FlushAllHWReg(); + CALLFunc((u32)psxBranchTest); + Return(); + + branch = 2; +} + +// + +static void (*recBSC[64])() = { + recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ, + recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI , + recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL, + recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL, + recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL, + recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL +}; + +static void (*recSPC[64])() = { + recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV, + recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL, + recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL, + recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL, + recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR , + recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL +}; + +static void (*recREG[32])() = { + recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL +}; + +static void (*recCP0[32])() = { + recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL +}; + +static void (*recCP2[64])() = { + recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00 + recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08 + recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10 + recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18 + recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20 + recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28 + recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30 + recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38 +}; + +static void (*recCP2BSC[32])() = { + recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, 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 +}; + +static void recRecompile() { + //static int recCount = 0; + char *p; + u32 *ptr; + int i; + + cop2readypc = 0; + idlecyclecount = 0; + + // initialize state variables + UniqueRegAlloc = 1; + HWRegUseCount = 0; + DstCPUReg = -1; + memset(HWRegisters, 0, sizeof(HWRegisters)); + for (i=0; i<NUM_HW_REGISTERS; i++) + HWRegisters[i].code = cpuHWRegisters[NUM_HW_REGISTERS-i-1]; + + // reserve the special psxReg register + HWRegisters[0].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED; + HWRegisters[0].private = PSXREGS; + HWRegisters[0].k = (u32)&psxRegs; + + HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED; + HWRegisters[1].private = PSXMEM; + HWRegisters[1].k = (u32)&psxM; + + // reserve the special psxRegs.cycle register + //HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED; + //HWRegisters[1].private = CYCLECOUNT; + + //memset(iRegs, 0, sizeof(iRegs)); + for (i=0; i<NUM_REGISTERS; i++) { + iRegs[i].state = ST_UNK; + iRegs[i].reg = -1; + } + iRegs[0].k = 0; + iRegs[0].state = ST_CONST; + + /* if ppcPtr reached the mem limit reset whole mem */ + if (((u32)ppcPtr - (u32)recMem) >= (RECMEM_SIZE - 0x10000)) + recReset(); + + ppcAlign(/*32*/4); + ptr = ppcPtr; + + // give us write access + //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE); + + // tell the LUT where to find us + PC_REC32(psxRegs.pc) = (u32)ppcPtr; + + pcold = pc = psxRegs.pc; + + //SysPrintf("RecCount: %i\n", recCount++); + + for (count=0; count<500;) { + p = (char *)PSXM(pc); + if (p == NULL) recError(); + psxRegs.code = SWAP32(*(u32 *)p); +/* + if ((psxRegs.code >> 26) == 0x23) { // LW + int i; + u32 code; + + for (i=1;; i++) { + p = (char *)PSXM(pc+i*4); + if (p == NULL) recError(); + code = *(u32 *)p; + + if ((code >> 26) != 0x23 || + _fRs_(code) != _Rs_ || + _fImm_(code) != (_Imm_+i*4)) + break; + } + if (i > 1) { + recLWBlock(i); + pc = pc + i*4; continue; + } + } + + if ((psxRegs.code >> 26) == 0x2b) { // SW + int i; + u32 code; + + for (i=1;; i++) { + p = (char *)PSXM(pc+i*4); + if (p == NULL) recError(); + code = *(u32 *)p; + + if ((code >> 26) != 0x2b || + _fRs_(code) != _Rs_ || + _fImm_(code) != (_Imm_+i*4)) + break; + } + if (i > 1) { + recSWBlock(i); + pc = pc + i*4; continue; + } + }*/ + + pc+=4; count++; +// iFlushRegs(0); // test + recBSC[psxRegs.code>>26](); + + if (branch) { + branch = 0; + //if (dump) iDumpBlock(ptr); + goto done; + } + } + + iFlushRegs(pc); + + LIW(PutHWRegSpecial(PSXPC), pc); + + iRet(); + +done:; +#if 0 + MakeDataExecutable(ptr, ((u8*)ppcPtr)-((u8*)ptr)); +#else + u32 a = (u32)(u8*)ptr; + while(a < (u32)(u8*)ppcPtr) { + __asm__ __volatile__("icbi 0,%0" : : "r" (a)); + __asm__ __volatile__("dcbst 0,%0" : : "r" (a)); + a += 4; + } + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); +#endif + +#if 1 + sprintf((char *)ppcPtr, "PC=%08x", pcold); + ppcPtr += strlen((char *)ppcPtr); +#endif + + //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ/*|PROT_WRITE*/); +} + + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; + +#endif diff --git a/libpcsxcore/ppf.c b/libpcsxcore/ppf.c index a5caca5f..fd8d32ec 100644..100755 --- a/libpcsxcore/ppf.c +++ b/libpcsxcore/ppf.c @@ -1,396 +1,396 @@ -/* PPF/SBI Support for PCSX-Reloaded
- * Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
- * Copyright (c) 2010, shalma.
- *
- * PPF code based on P.E.Op.S CDR Plugin by Pete Bernert.
- * Copyright (c) 2002, Pete Bernert.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "psxcommon.h"
-#include "ppf.h"
-#include "cdrom.h"
-
-typedef struct tagPPF_DATA {
- s32 addr;
- s32 pos;
- s32 anz;
- struct tagPPF_DATA *pNext;
-} PPF_DATA;
-
-typedef struct tagPPF_CACHE {
- s32 addr;
- struct tagPPF_DATA *pNext;
-} PPF_CACHE;
-
-static PPF_CACHE *ppfCache = NULL;
-static PPF_DATA *ppfHead = NULL, *ppfLast = NULL;
-static int iPPFNum = 0;
-
-// using a linked data list, and address array
-static void FillPPFCache() {
- PPF_DATA *p;
- PPF_CACHE *pc;
- s32 lastaddr;
-
- p = ppfHead;
- lastaddr = -1;
- iPPFNum = 0;
-
- while (p != NULL) {
- if (p->addr != lastaddr) iPPFNum++;
- lastaddr = p->addr;
- p = p->pNext;
- }
-
- if (iPPFNum <= 0) return;
-
- pc = ppfCache = (PPF_CACHE *)malloc(iPPFNum * sizeof(PPF_CACHE));
-
- iPPFNum--;
- p = ppfHead;
- lastaddr = -1;
-
- while (p != NULL) {
- if (p->addr != lastaddr) {
- pc->addr = p->addr;
- pc->pNext = p;
- pc++;
- }
- lastaddr = p->addr;
- p = p->pNext;
- }
-}
-
-void FreePPFCache() {
- PPF_DATA *p = ppfHead;
- void *pn;
-
- while (p != NULL) {
- pn = p->pNext;
- free(p);
- p = (PPF_DATA *)pn;
- }
- ppfHead = NULL;
- ppfLast = NULL;
-
- if (ppfCache != NULL) free(ppfCache);
- ppfCache = NULL;
-}
-
-void CheckPPFCache(unsigned char *pB, unsigned char m, unsigned char s, unsigned char f) {
- PPF_CACHE *pcstart, *pcend, *pcpos;
- int addr = MSF2SECT(btoi(m), btoi(s), btoi(f)), pos, anz, start;
-
- if (ppfCache == NULL) return;
-
- pcstart = ppfCache;
- if (addr < pcstart->addr) return;
- pcend = ppfCache + iPPFNum;
- if (addr > pcend->addr) return;
-
- while (1) {
- if (addr == pcend->addr) { pcpos = pcend; break; }
-
- pcpos = pcstart + (pcend - pcstart) / 2;
- if (pcpos == pcstart) break;
- if (addr < pcpos->addr) {
- pcend = pcpos;
- continue;
- }
- if (addr > pcpos->addr) {
- pcstart = pcpos;
- continue;
- }
- break;
- }
-
- if (addr == pcpos->addr) {
- PPF_DATA *p = pcpos->pNext;
- while (p != NULL && p->addr == addr) {
- pos = p->pos - (CD_FRAMESIZE_RAW - DATA_SIZE);
- anz = p->anz;
- if (pos < 0) { start = -pos; pos = 0; anz -= start; }
- else start = 0;
- memcpy(pB + pos, (unsigned char *)(p + 1) + start, anz);
- p = p->pNext;
- }
- }
-}
-
-static void AddToPPF(s32 ladr, s32 pos, s32 anz, unsigned char *ppfmem) {
- if (ppfHead == NULL) {
- ppfHead = (PPF_DATA *)malloc(sizeof(PPF_DATA) + anz);
- ppfHead->addr = ladr;
- ppfHead->pNext = NULL;
- ppfHead->pos = pos;
- ppfHead->anz = anz;
- memcpy(ppfHead + 1, ppfmem, anz);
- iPPFNum = 1;
- ppfLast = ppfHead;
- } else {
- PPF_DATA *p = ppfHead;
- PPF_DATA *plast = NULL;
- PPF_DATA *padd;
-
- if (ladr > ppfLast->addr || (ladr == ppfLast->addr && pos > ppfLast->pos)) {
- p = NULL;
- plast = ppfLast;
- } else {
- while (p != NULL) {
- if (ladr < p->addr) break;
- if (ladr == p->addr) {
- while (p && ladr == p->addr && pos > p->pos) {
- plast = p;
- p = p->pNext;
- }
- break;
- }
- plast = p;
- p = p->pNext;
- }
- }
-
- padd = (PPF_DATA *)malloc(sizeof(PPF_DATA) + anz);
- padd->addr = ladr;
- padd->pNext = p;
- padd->pos = pos;
- padd->anz = anz;
- memcpy(padd + 1, ppfmem, anz);
- iPPFNum++;
- if (plast == NULL) ppfHead = padd;
- else plast->pNext = padd;
-
- if (padd->pNext == NULL) ppfLast = padd;
- }
-}
-
-void BuildPPFCache() {
- FILE *ppffile;
- char buffer[12];
- char method, undo = 0, blockcheck = 0;
- int dizlen, dizyn;
- unsigned char ppfmem[512];
- char szPPF[MAXPATHLEN];
- int count, seekpos, pos;
- u32 anz; // use 32-bit to avoid stupid overflows
- s32 ladr, off, anx;
-
- FreePPFCache();
-
- if (CdromId[0] == '\0') return;
-
- // Generate filename in the format of SLUS_123.45
- buffer[0] = toupper(CdromId[0]);
- buffer[1] = toupper(CdromId[1]);
- buffer[2] = toupper(CdromId[2]);
- buffer[3] = toupper(CdromId[3]);
- buffer[4] = '_';
- buffer[5] = CdromId[4];
- buffer[6] = CdromId[5];
- buffer[7] = CdromId[6];
- buffer[8] = '.';
- buffer[9] = CdromId[7];
- buffer[10] = CdromId[8];
- buffer[11] = '\0';
-
- sprintf(szPPF, "%s%s", Config.PatchesDir, buffer);
-
- ppffile = fopen(szPPF, "rb");
- if (ppffile == NULL) return;
-
- memset(buffer, 0, 5);
- fread(buffer, 3, 1, ppffile);
-
- if (strcmp(buffer, "PPF") != 0) {
- SysPrintf(_("Invalid PPF patch: %s.\n"), szPPF);
- fclose(ppffile);
- return;
- }
-
- fseek(ppffile, 5, SEEK_SET);
- method = fgetc(ppffile);
-
- switch (method) {
- case 0: // ppf1
- fseek(ppffile, 0, SEEK_END);
- count = ftell(ppffile);
- count -= 56;
- seekpos = 56;
- break;
-
- case 1: // ppf2
- fseek(ppffile, -8, SEEK_END);
-
- memset(buffer, 0, 5);
- fread(buffer, 4, 1, ppffile);
-
- if (strcmp(".DIZ", buffer) != 0) {
- dizyn = 0;
- } else {
- fread(&dizlen, 4, 1, ppffile);
- dizlen = SWAP32(dizlen);
- dizyn = 1;
- }
-
- fseek(ppffile, 0, SEEK_END);
- count = ftell(ppffile);
-
- if (dizyn == 0) {
- count -= 1084;
- seekpos = 1084;
- } else {
- count -= 1084;
- count -= 38;
- count -= dizlen;
- seekpos = 1084;
- }
- break;
-
- case 2: // ppf3
- fseek(ppffile, 57, SEEK_SET);
- blockcheck = fgetc(ppffile);
- undo = fgetc(ppffile);
-
- fseek(ppffile, -6, SEEK_END);
- memset(buffer, 0, 5);
- fread(buffer, 4, 1, ppffile);
- dizlen = 0;
-
- if (strcmp(".DIZ", buffer) == 0) {
- fseek(ppffile, -2, SEEK_END);
- fread(&dizlen, 2, 1, ppffile);
- dizlen = SWAP32(dizlen);
- dizlen += 36;
- }
-
- fseek(ppffile, 0, SEEK_END);
- count = ftell(ppffile);
- count -= dizlen;
-
- if (blockcheck) {
- seekpos = 1084;
- count -= 1084;
- } else {
- seekpos = 60;
- count -= 60;
- }
- break;
-
- default:
- fclose(ppffile);
- SysPrintf(_("Unsupported PPF version (%d).\n"), method + 1);
- return;
- }
-
- // now do the data reading
- do {
- fseek(ppffile, seekpos, SEEK_SET);
- fread(&pos, 4, 1, ppffile);
- pos = SWAP32(pos);
-
- if (method == 2) fread(buffer, 4, 1, ppffile); // skip 4 bytes on ppf3 (no int64 support here)
-
- anz = fgetc(ppffile);
- fread(ppfmem, anz, 1, ppffile);
-
- ladr = pos / CD_FRAMESIZE_RAW;
- off = pos % CD_FRAMESIZE_RAW;
-
- if (off + anz > CD_FRAMESIZE_RAW) {
- anx = off + anz - CD_FRAMESIZE_RAW;
- anz -= (unsigned char)anx;
- AddToPPF(ladr + 1, 0, anx, &ppfmem[anz]);
- }
-
- AddToPPF(ladr, off, anz, ppfmem); // add to link list
-
- if (method == 2) {
- if (undo) anz += anz;
- anz += 4;
- }
-
- seekpos = seekpos + 5 + anz;
- count = count - 5 - anz;
- } while (count != 0); // loop til end
-
- fclose(ppffile);
-
- FillPPFCache(); // build address array
-
- SysPrintf(_("Loaded PPF %d.0 patch: %s.\n"), method + 1, szPPF);
-}
-
-// redump.org SBI files
-static u8 sbitime[256][3], sbicount;
-
-void LoadSBI() {
- FILE *sbihandle;
- char buffer[16], sbifile[MAXPATHLEN];
-
- if (CdromId[0] == '\0') return;
-
- // Generate filename in the format of SLUS_123.45.sbi
- buffer[0] = toupper(CdromId[0]);
- buffer[1] = toupper(CdromId[1]);
- buffer[2] = toupper(CdromId[2]);
- buffer[3] = toupper(CdromId[3]);
- buffer[4] = '_';
- buffer[5] = CdromId[4];
- buffer[6] = CdromId[5];
- buffer[7] = CdromId[6];
- buffer[8] = '.';
- buffer[9] = CdromId[7];
- buffer[10] = CdromId[8];
- buffer[11] = '.';
- buffer[12] = 's';
- buffer[13] = 'b';
- buffer[14] = 'i';
- buffer[15] = '\0';
-
- sprintf(sbifile, "%s%s", Config.PatchesDir, buffer);
-
- // init
- sbicount = 0;
-
- sbihandle = fopen(sbifile, "rb");
- if (sbihandle == NULL) return;
-
- // 4-byte SBI header
- fread(buffer, 1, 4, sbihandle);
- while (!feof(sbihandle)) {
- fread(sbitime[sbicount++], 1, 3, sbihandle);
- fread(buffer, 1, 11, sbihandle);
- }
-
- fclose(sbihandle);
-
- SysPrintf(_("Loaded SBI file: %s.\n"), sbifile);
-}
-
-boolean CheckSBI(const u8 *time) {
- int lcv;
-
- // both BCD format
- for (lcv = 0; lcv < sbicount; lcv++) {
- if (time[0] == sbitime[lcv][0] &&
- time[1] == sbitime[lcv][1] &&
- time[2] == sbitime[lcv][2])
- return TRUE;
- }
-
- return FALSE;
-}
+/* PPF/SBI Support for PCSX-Reloaded + * Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>. + * Copyright (c) 2010, shalma. + * + * PPF code based on P.E.Op.S CDR Plugin by Pete Bernert. + * Copyright (c) 2002, Pete Bernert. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "psxcommon.h" +#include "ppf.h" +#include "cdrom.h" + +typedef struct tagPPF_DATA { + s32 addr; + s32 pos; + s32 anz; + struct tagPPF_DATA *pNext; +} PPF_DATA; + +typedef struct tagPPF_CACHE { + s32 addr; + struct tagPPF_DATA *pNext; +} PPF_CACHE; + +static PPF_CACHE *ppfCache = NULL; +static PPF_DATA *ppfHead = NULL, *ppfLast = NULL; +static int iPPFNum = 0; + +// using a linked data list, and address array +static void FillPPFCache() { + PPF_DATA *p; + PPF_CACHE *pc; + s32 lastaddr; + + p = ppfHead; + lastaddr = -1; + iPPFNum = 0; + + while (p != NULL) { + if (p->addr != lastaddr) iPPFNum++; + lastaddr = p->addr; + p = p->pNext; + } + + if (iPPFNum <= 0) return; + + pc = ppfCache = (PPF_CACHE *)malloc(iPPFNum * sizeof(PPF_CACHE)); + + iPPFNum--; + p = ppfHead; + lastaddr = -1; + + while (p != NULL) { + if (p->addr != lastaddr) { + pc->addr = p->addr; + pc->pNext = p; + pc++; + } + lastaddr = p->addr; + p = p->pNext; + } +} + +void FreePPFCache() { + PPF_DATA *p = ppfHead; + void *pn; + + while (p != NULL) { + pn = p->pNext; + free(p); + p = (PPF_DATA *)pn; + } + ppfHead = NULL; + ppfLast = NULL; + + if (ppfCache != NULL) free(ppfCache); + ppfCache = NULL; +} + +void CheckPPFCache(unsigned char *pB, unsigned char m, unsigned char s, unsigned char f) { + PPF_CACHE *pcstart, *pcend, *pcpos; + int addr = MSF2SECT(btoi(m), btoi(s), btoi(f)), pos, anz, start; + + if (ppfCache == NULL) return; + + pcstart = ppfCache; + if (addr < pcstart->addr) return; + pcend = ppfCache + iPPFNum; + if (addr > pcend->addr) return; + + while (1) { + if (addr == pcend->addr) { pcpos = pcend; break; } + + pcpos = pcstart + (pcend - pcstart) / 2; + if (pcpos == pcstart) break; + if (addr < pcpos->addr) { + pcend = pcpos; + continue; + } + if (addr > pcpos->addr) { + pcstart = pcpos; + continue; + } + break; + } + + if (addr == pcpos->addr) { + PPF_DATA *p = pcpos->pNext; + while (p != NULL && p->addr == addr) { + pos = p->pos - (CD_FRAMESIZE_RAW - DATA_SIZE); + anz = p->anz; + if (pos < 0) { start = -pos; pos = 0; anz -= start; } + else start = 0; + memcpy(pB + pos, (unsigned char *)(p + 1) + start, anz); + p = p->pNext; + } + } +} + +static void AddToPPF(s32 ladr, s32 pos, s32 anz, unsigned char *ppfmem) { + if (ppfHead == NULL) { + ppfHead = (PPF_DATA *)malloc(sizeof(PPF_DATA) + anz); + ppfHead->addr = ladr; + ppfHead->pNext = NULL; + ppfHead->pos = pos; + ppfHead->anz = anz; + memcpy(ppfHead + 1, ppfmem, anz); + iPPFNum = 1; + ppfLast = ppfHead; + } else { + PPF_DATA *p = ppfHead; + PPF_DATA *plast = NULL; + PPF_DATA *padd; + + if (ladr > ppfLast->addr || (ladr == ppfLast->addr && pos > ppfLast->pos)) { + p = NULL; + plast = ppfLast; + } else { + while (p != NULL) { + if (ladr < p->addr) break; + if (ladr == p->addr) { + while (p && ladr == p->addr && pos > p->pos) { + plast = p; + p = p->pNext; + } + break; + } + plast = p; + p = p->pNext; + } + } + + padd = (PPF_DATA *)malloc(sizeof(PPF_DATA) + anz); + padd->addr = ladr; + padd->pNext = p; + padd->pos = pos; + padd->anz = anz; + memcpy(padd + 1, ppfmem, anz); + iPPFNum++; + if (plast == NULL) ppfHead = padd; + else plast->pNext = padd; + + if (padd->pNext == NULL) ppfLast = padd; + } +} + +void BuildPPFCache() { + FILE *ppffile; + char buffer[12]; + char method, undo = 0, blockcheck = 0; + int dizlen, dizyn; + unsigned char ppfmem[512]; + char szPPF[MAXPATHLEN]; + int count, seekpos, pos; + u32 anz; // use 32-bit to avoid stupid overflows + s32 ladr, off, anx; + + FreePPFCache(); + + if (CdromId[0] == '\0') return; + + // Generate filename in the format of SLUS_123.45 + buffer[0] = toupper(CdromId[0]); + buffer[1] = toupper(CdromId[1]); + buffer[2] = toupper(CdromId[2]); + buffer[3] = toupper(CdromId[3]); + buffer[4] = '_'; + buffer[5] = CdromId[4]; + buffer[6] = CdromId[5]; + buffer[7] = CdromId[6]; + buffer[8] = '.'; + buffer[9] = CdromId[7]; + buffer[10] = CdromId[8]; + buffer[11] = '\0'; + + sprintf(szPPF, "%s%s", Config.PatchesDir, buffer); + + ppffile = fopen(szPPF, "rb"); + if (ppffile == NULL) return; + + memset(buffer, 0, 5); + fread(buffer, 3, 1, ppffile); + + if (strcmp(buffer, "PPF") != 0) { + SysPrintf(_("Invalid PPF patch: %s.\n"), szPPF); + fclose(ppffile); + return; + } + + fseek(ppffile, 5, SEEK_SET); + method = fgetc(ppffile); + + switch (method) { + case 0: // ppf1 + fseek(ppffile, 0, SEEK_END); + count = ftell(ppffile); + count -= 56; + seekpos = 56; + break; + + case 1: // ppf2 + fseek(ppffile, -8, SEEK_END); + + memset(buffer, 0, 5); + fread(buffer, 4, 1, ppffile); + + if (strcmp(".DIZ", buffer) != 0) { + dizyn = 0; + } else { + fread(&dizlen, 4, 1, ppffile); + dizlen = SWAP32(dizlen); + dizyn = 1; + } + + fseek(ppffile, 0, SEEK_END); + count = ftell(ppffile); + + if (dizyn == 0) { + count -= 1084; + seekpos = 1084; + } else { + count -= 1084; + count -= 38; + count -= dizlen; + seekpos = 1084; + } + break; + + case 2: // ppf3 + fseek(ppffile, 57, SEEK_SET); + blockcheck = fgetc(ppffile); + undo = fgetc(ppffile); + + fseek(ppffile, -6, SEEK_END); + memset(buffer, 0, 5); + fread(buffer, 4, 1, ppffile); + dizlen = 0; + + if (strcmp(".DIZ", buffer) == 0) { + fseek(ppffile, -2, SEEK_END); + fread(&dizlen, 2, 1, ppffile); + dizlen = SWAP32(dizlen); + dizlen += 36; + } + + fseek(ppffile, 0, SEEK_END); + count = ftell(ppffile); + count -= dizlen; + + if (blockcheck) { + seekpos = 1084; + count -= 1084; + } else { + seekpos = 60; + count -= 60; + } + break; + + default: + fclose(ppffile); + SysPrintf(_("Unsupported PPF version (%d).\n"), method + 1); + return; + } + + // now do the data reading + do { + fseek(ppffile, seekpos, SEEK_SET); + fread(&pos, 4, 1, ppffile); + pos = SWAP32(pos); + + if (method == 2) fread(buffer, 4, 1, ppffile); // skip 4 bytes on ppf3 (no int64 support here) + + anz = fgetc(ppffile); + fread(ppfmem, anz, 1, ppffile); + + ladr = pos / CD_FRAMESIZE_RAW; + off = pos % CD_FRAMESIZE_RAW; + + if (off + anz > CD_FRAMESIZE_RAW) { + anx = off + anz - CD_FRAMESIZE_RAW; + anz -= (unsigned char)anx; + AddToPPF(ladr + 1, 0, anx, &ppfmem[anz]); + } + + AddToPPF(ladr, off, anz, ppfmem); // add to link list + + if (method == 2) { + if (undo) anz += anz; + anz += 4; + } + + seekpos = seekpos + 5 + anz; + count = count - 5 - anz; + } while (count != 0); // loop til end + + fclose(ppffile); + + FillPPFCache(); // build address array + + SysPrintf(_("Loaded PPF %d.0 patch: %s.\n"), method + 1, szPPF); +} + +// redump.org SBI files +static u8 sbitime[256][3], sbicount; + +void LoadSBI() { + FILE *sbihandle; + char buffer[16], sbifile[MAXPATHLEN]; + + if (CdromId[0] == '\0') return; + + // Generate filename in the format of SLUS_123.45.sbi + buffer[0] = toupper(CdromId[0]); + buffer[1] = toupper(CdromId[1]); + buffer[2] = toupper(CdromId[2]); + buffer[3] = toupper(CdromId[3]); + buffer[4] = '_'; + buffer[5] = CdromId[4]; + buffer[6] = CdromId[5]; + buffer[7] = CdromId[6]; + buffer[8] = '.'; + buffer[9] = CdromId[7]; + buffer[10] = CdromId[8]; + buffer[11] = '.'; + buffer[12] = 's'; + buffer[13] = 'b'; + buffer[14] = 'i'; + buffer[15] = '\0'; + + sprintf(sbifile, "%s%s", Config.PatchesDir, buffer); + + // init + sbicount = 0; + + sbihandle = fopen(sbifile, "rb"); + if (sbihandle == NULL) return; + + // 4-byte SBI header + fread(buffer, 1, 4, sbihandle); + while (!feof(sbihandle)) { + fread(sbitime[sbicount++], 1, 3, sbihandle); + fread(buffer, 1, 11, sbihandle); + } + + fclose(sbihandle); + + SysPrintf(_("Loaded SBI file: %s.\n"), sbifile); +} + +boolean CheckSBI(const u8 *time) { + int lcv; + + // both BCD format + for (lcv = 0; lcv < sbicount; lcv++) { + if (time[0] == sbitime[lcv][0] && + time[1] == sbitime[lcv][1] && + time[2] == sbitime[lcv][2]) + return TRUE; + } + + return FALSE; +} diff --git a/libpcsxcore/psemu_plugin_defs.h b/libpcsxcore/psemu_plugin_defs.h index f0ba8fcf..d1b05ac3 100644..100755 --- a/libpcsxcore/psemu_plugin_defs.h +++ b/libpcsxcore/psemu_plugin_defs.h @@ -1,285 +1,285 @@ -#ifndef _PSEMU_PLUGIN_DEFS_H
-#define _PSEMU_PLUGIN_DEFS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// header version
-#define _PPDK_HEADER_VERSION 3
-
-#define PLUGIN_VERSION 1
-
-// plugin type returned by PSEgetLibType (types can be merged if plugin is multi type!)
-#define PSE_LT_CDR 1
-#define PSE_LT_GPU 2
-#define PSE_LT_SPU 4
-#define PSE_LT_PAD 8
-#define PSE_LT_NET 16
-
-// DLL function return codes
-#define PSE_ERR_SUCCESS 0 // every function in DLL if completed sucessfully should return this value
-#define PSE_ERR_FATAL -1 // undefined error but fatal one, that kills all functionality
-
-// XXX_Init return values
-// Those return values apply to all libraries
-// currently obsolete - preserved for compatibilty
-
-#define PSE_INIT_ERR_SUCCESS 0 // initialization went OK
-#define PSE_INIT_ERR_NOTCONFIGURED -2 // this driver is not configured
-#define PSE_INIT_ERR_NOHARDWARE -3 // this driver can not operate properly on this hardware or hardware is not detected
-
-/* GPU PlugIn */
-
-// GPU_Test return values
-
-// sucess, everything configured, and went OK.
-#define PSE_GPU_ERR_SUCCESS 0
-
-// ERRORS
-// this error might be returned as critical error but none of below
-#define PSE_GPU_ERR -20
-
-
-// this driver is not configured
-#define PSE_GPU_ERR_NOTCONFIGURED PSE_GPU_ERR - 1
-// this driver failed Init
-#define PSE_GPU_ERR_INIT PSE_GPU_ERR - 2
-
-// WARNINGS
-// this warning might be returned as undefined warning but allowing driver to continue
-#define PSE_GPU_WARN 20
-
-// GPU_Query - will be implemented soon
-
-typedef struct
-{
- uint32_t flags;
- uint32_t status;
- void* window;
- unsigned char reserved[100];
-} gpuQueryS;
-
-// gpuQueryS.flags
-// if driver can operate in both modes it must support GPU_changeMode();
-#define PSE_GPU_FLAGS_FULLSCREEN 1 // this driver can operate in fullscreen mode
-#define PSE_GPU_FLAGS_WINDOWED 2 // this driver can operate in windowed mode
-
-// gpuQueryS.status
-#define PSE_GPU_STATUS_WINDOWWRONG 1 // this driver cannot operate in this windowed mode
-
-// GPU_Query End - will be implemented in v2
-
-
-/* CDR PlugIn */
-
-// CDR_Test return values
-
-// sucess, everything configured, and went OK.
-#define PSE_CDR_ERR_SUCCESS 0
-
-// general failure (error undefined)
-#define PSE_CDR_ERR_FAILURE -1
-
-// ERRORS
-#define PSE_CDR_ERR -40
-// this driver is not configured
-#define PSE_CDR_ERR_NOTCONFIGURED PSE_CDR_ERR - 0
-// if this driver is unable to read data from medium
-#define PSE_CDR_ERR_NOREAD PSE_CDR_ERR - 1
-
-// WARNINGS
-#define PSE_CDR_WARN 40
-// if this driver emulates lame mode ie. can read only 2048 tracks and sector header is emulated
-// this might happen to CDROMS that do not support RAW mode reading - surelly it will kill many games
-#define PSE_CDR_WARN_LAMECD PSE_CDR_WARN + 0
-
-
-
-
-/* SPU PlugIn */
-
-// some info retricted (now!)
-
-// sucess, everything configured, and went OK.
-#define PSE_SPU_ERR_SUCCESS 0
-
-// ERRORS
-// this error might be returned as critical error but none of below
-#define PSE_SPU_ERR -60
-
-// this driver is not configured
-#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1
-// this driver failed Init
-#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2
-
-
-// WARNINGS
-// this warning might be returned as undefined warning but allowing driver to continue
-#define PSE_SPU_WARN 60
-
-
-
-
-/* PAD PlugIn */
-
-/*
-
- functions that must be exported from PAD Plugin
-
- long PADinit(long flags); // called only once when PSEmu Starts
- void PADshutdown(void); // called when PSEmu exits
- long PADopen(PadInitS *); // called when PSEmu is running program
- long PADclose(void);
- long PADconfigure(void);
- void PADabout(void);
- long PADtest(void); // called from Configure Dialog and after PADopen();
- long PADquery(void);
-
- unsigned char PADstartPoll(int);
- unsigned char PADpoll(unsigned char);
-
-*/
-
-// PADquery responses (notice - values ORed)
-// PSEmu will use them also in PADinit to tell Plugin which Ports will use
-// notice that PSEmu will call PADinit and PADopen only once when they are from
-// same plugin
-
-// might be used in port 1
-#define PSE_PAD_USE_PORT1 1
-// might be used in port 2
-#define PSE_PAD_USE_PORT2 2
-
-
-
-// MOUSE SCPH-1030
-#define PSE_PAD_TYPE_MOUSE 1
-// NEGCON - 16 button analog controller SLPH-00001
-#define PSE_PAD_TYPE_NEGCON 2
-// GUN CONTROLLER - gun controller SLPH-00014 from Konami
-#define PSE_PAD_TYPE_GUN 3
-// STANDARD PAD SCPH-1080, SCPH-1150
-#define PSE_PAD_TYPE_STANDARD 4
-// ANALOG JOYSTICK SCPH-1110
-#define PSE_PAD_TYPE_ANALOGJOY 5
-// GUNCON - gun controller SLPH-00034 from Namco
-#define PSE_PAD_TYPE_GUNCON 6
-// ANALOG CONTROLLER SCPH-1150
-#define PSE_PAD_TYPE_ANALOGPAD 7
-
-
-// sucess, everything configured, and went OK.
-#define PSE_PAD_ERR_SUCCESS 0
-// general plugin failure (undefined error)
-#define PSE_PAD_ERR_FAILURE -1
-
-
-// ERRORS
-// this error might be returned as critical error but none of below
-#define PSE_PAD_ERR -80
-// this driver is not configured
-#define PSE_PAD_ERR_NOTCONFIGURED PSE_PAD_ERR - 1
-// this driver failed Init
-#define PSE_PAD_ERR_INIT PSE_PAD_ERR - 2
-
-
-// WARNINGS
-// this warning might be returned as undefined warning but allowing driver to continue
-#define PSE_PAD_WARN 80
-
-
-typedef struct
-{
- // controler type - fill it withe predefined values above
- unsigned char controllerType;
-
- // status of buttons - every controller fills this field
- unsigned short buttonStatus;
-
- // for analog pad fill those next 4 bytes
- // values are analog in range 0-255 where 127 is center position
- unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY;
-
- // for mouse fill those next 2 bytes
- // values are in range -128 - 127
- unsigned char moveX, moveY;
-
- unsigned char reserved[91];
-
-} PadDataS;
-
-/* NET PlugIn v2 */
-/* Added by linuzappz@pcsx.net */
-
-/* Modes bits for NETsendData/NETrecvData */
-#define PSE_NET_BLOCKING 0x00000000
-#define PSE_NET_NONBLOCKING 0x00000001
-
-/* note: unsupported fields should be zeroed.
-
-typedef struct {
- char EmuName[32];
- char CdromID[9]; // ie. 'SCPH12345', no \0 trailing character
- char CdromLabel[11];
- void *psxMem;
- GPUshowScreenPic GPU_showScreenPic;
- GPUdisplayText GPU_displayText;
- PADsetSensitive PAD_setSensitive;
- char GPUpath[256];
- char SPUpath[256];
- char CDRpath[256];
- char MCD1path[256];
- char MCD2path[256];
- char BIOSpath[256]; // 'HLE' for internal bios
- char Unused[1024];
-} netInfo;
-
-*/
-
-/*
- basic funcs:
-
- long NETopen(HWND hWnd)
- opens the connection.
- shall return 0 on success, else -1.
- -1 is also returned if the user selects offline mode.
-
- long NETclose()
- closes the connection.
- shall return 0 on success, else -1.
-
- void NETpause()
- this is called when the user paused the emulator.
-
- void NETresume()
- this is called when the user resumed the emulator.
-
- long NETqueryPlayer()
- returns player number
-
- long NETsendPadData(void *pData, int Size)
- this should be called for the first pad only on each side.
-
- long NETrecvPadData(void *pData, int Pad)
- call this for Pad 1/2 to get the data sent by the above func.
-
- extended funcs:
-
- long NETsendData(void *pData, int Size, int Mode)
- sends Size bytes from pData to the other side.
-
- long NETrecvData(void *pData, int Size, int Mode)
- receives Size bytes from pData to the other side.
-
- void NETsetInfo(netInfo *info);
- sets the netInfo struct.
-
- void NETkeypressed(int key) (linux only)
- key is a XK_?? (X11) keycode.
-*/
-
-#ifdef __cplusplus
-}
-#endif
-#endif // _PSEMU_PLUGIN_DEFS_H
+#ifndef _PSEMU_PLUGIN_DEFS_H +#define _PSEMU_PLUGIN_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// header version +#define _PPDK_HEADER_VERSION 3 + +#define PLUGIN_VERSION 1 + +// plugin type returned by PSEgetLibType (types can be merged if plugin is multi type!) +#define PSE_LT_CDR 1 +#define PSE_LT_GPU 2 +#define PSE_LT_SPU 4 +#define PSE_LT_PAD 8 +#define PSE_LT_NET 16 + +// DLL function return codes +#define PSE_ERR_SUCCESS 0 // every function in DLL if completed sucessfully should return this value +#define PSE_ERR_FATAL -1 // undefined error but fatal one, that kills all functionality + +// XXX_Init return values +// Those return values apply to all libraries +// currently obsolete - preserved for compatibilty + +#define PSE_INIT_ERR_SUCCESS 0 // initialization went OK +#define PSE_INIT_ERR_NOTCONFIGURED -2 // this driver is not configured +#define PSE_INIT_ERR_NOHARDWARE -3 // this driver can not operate properly on this hardware or hardware is not detected + +/* GPU PlugIn */ + +// GPU_Test return values + +// sucess, everything configured, and went OK. +#define PSE_GPU_ERR_SUCCESS 0 + +// ERRORS +// this error might be returned as critical error but none of below +#define PSE_GPU_ERR -20 + + +// this driver is not configured +#define PSE_GPU_ERR_NOTCONFIGURED PSE_GPU_ERR - 1 +// this driver failed Init +#define PSE_GPU_ERR_INIT PSE_GPU_ERR - 2 + +// WARNINGS +// this warning might be returned as undefined warning but allowing driver to continue +#define PSE_GPU_WARN 20 + +// GPU_Query - will be implemented soon + +typedef struct +{ + uint32_t flags; + uint32_t status; + void* window; + unsigned char reserved[100]; +} gpuQueryS; + +// gpuQueryS.flags +// if driver can operate in both modes it must support GPU_changeMode(); +#define PSE_GPU_FLAGS_FULLSCREEN 1 // this driver can operate in fullscreen mode +#define PSE_GPU_FLAGS_WINDOWED 2 // this driver can operate in windowed mode + +// gpuQueryS.status +#define PSE_GPU_STATUS_WINDOWWRONG 1 // this driver cannot operate in this windowed mode + +// GPU_Query End - will be implemented in v2 + + +/* CDR PlugIn */ + +// CDR_Test return values + +// sucess, everything configured, and went OK. +#define PSE_CDR_ERR_SUCCESS 0 + +// general failure (error undefined) +#define PSE_CDR_ERR_FAILURE -1 + +// ERRORS +#define PSE_CDR_ERR -40 +// this driver is not configured +#define PSE_CDR_ERR_NOTCONFIGURED PSE_CDR_ERR - 0 +// if this driver is unable to read data from medium +#define PSE_CDR_ERR_NOREAD PSE_CDR_ERR - 1 + +// WARNINGS +#define PSE_CDR_WARN 40 +// if this driver emulates lame mode ie. can read only 2048 tracks and sector header is emulated +// this might happen to CDROMS that do not support RAW mode reading - surelly it will kill many games +#define PSE_CDR_WARN_LAMECD PSE_CDR_WARN + 0 + + + + +/* SPU PlugIn */ + +// some info retricted (now!) + +// sucess, everything configured, and went OK. +#define PSE_SPU_ERR_SUCCESS 0 + +// ERRORS +// this error might be returned as critical error but none of below +#define PSE_SPU_ERR -60 + +// this driver is not configured +#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 +// this driver failed Init +#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 + + +// WARNINGS +// this warning might be returned as undefined warning but allowing driver to continue +#define PSE_SPU_WARN 60 + + + + +/* PAD PlugIn */ + +/* + + functions that must be exported from PAD Plugin + + long PADinit(long flags); // called only once when PSEmu Starts + void PADshutdown(void); // called when PSEmu exits + long PADopen(PadInitS *); // called when PSEmu is running program + long PADclose(void); + long PADconfigure(void); + void PADabout(void); + long PADtest(void); // called from Configure Dialog and after PADopen(); + long PADquery(void); + + unsigned char PADstartPoll(int); + unsigned char PADpoll(unsigned char); + +*/ + +// PADquery responses (notice - values ORed) +// PSEmu will use them also in PADinit to tell Plugin which Ports will use +// notice that PSEmu will call PADinit and PADopen only once when they are from +// same plugin + +// might be used in port 1 +#define PSE_PAD_USE_PORT1 1 +// might be used in port 2 +#define PSE_PAD_USE_PORT2 2 + + + +// MOUSE SCPH-1030 +#define PSE_PAD_TYPE_MOUSE 1 +// NEGCON - 16 button analog controller SLPH-00001 +#define PSE_PAD_TYPE_NEGCON 2 +// GUN CONTROLLER - gun controller SLPH-00014 from Konami +#define PSE_PAD_TYPE_GUN 3 +// STANDARD PAD SCPH-1080, SCPH-1150 +#define PSE_PAD_TYPE_STANDARD 4 +// ANALOG JOYSTICK SCPH-1110 +#define PSE_PAD_TYPE_ANALOGJOY 5 +// GUNCON - gun controller SLPH-00034 from Namco +#define PSE_PAD_TYPE_GUNCON 6 +// ANALOG CONTROLLER SCPH-1150 +#define PSE_PAD_TYPE_ANALOGPAD 7 + + +// sucess, everything configured, and went OK. +#define PSE_PAD_ERR_SUCCESS 0 +// general plugin failure (undefined error) +#define PSE_PAD_ERR_FAILURE -1 + + +// ERRORS +// this error might be returned as critical error but none of below +#define PSE_PAD_ERR -80 +// this driver is not configured +#define PSE_PAD_ERR_NOTCONFIGURED PSE_PAD_ERR - 1 +// this driver failed Init +#define PSE_PAD_ERR_INIT PSE_PAD_ERR - 2 + + +// WARNINGS +// this warning might be returned as undefined warning but allowing driver to continue +#define PSE_PAD_WARN 80 + + +typedef struct +{ + // controler type - fill it withe predefined values above + unsigned char controllerType; + + // status of buttons - every controller fills this field + unsigned short buttonStatus; + + // for analog pad fill those next 4 bytes + // values are analog in range 0-255 where 127 is center position + unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY; + + // for mouse fill those next 2 bytes + // values are in range -128 - 127 + unsigned char moveX, moveY; + + unsigned char reserved[91]; + +} PadDataS; + +/* NET PlugIn v2 */ +/* Added by linuzappz@pcsx.net */ + +/* Modes bits for NETsendData/NETrecvData */ +#define PSE_NET_BLOCKING 0x00000000 +#define PSE_NET_NONBLOCKING 0x00000001 + +/* note: unsupported fields should be zeroed. + +typedef struct { + char EmuName[32]; + char CdromID[9]; // ie. 'SCPH12345', no \0 trailing character + char CdromLabel[11]; + void *psxMem; + GPUshowScreenPic GPU_showScreenPic; + GPUdisplayText GPU_displayText; + PADsetSensitive PAD_setSensitive; + char GPUpath[256]; + char SPUpath[256]; + char CDRpath[256]; + char MCD1path[256]; + char MCD2path[256]; + char BIOSpath[256]; // 'HLE' for internal bios + char Unused[1024]; +} netInfo; + +*/ + +/* + basic funcs: + + long NETopen(HWND hWnd) + opens the connection. + shall return 0 on success, else -1. + -1 is also returned if the user selects offline mode. + + long NETclose() + closes the connection. + shall return 0 on success, else -1. + + void NETpause() + this is called when the user paused the emulator. + + void NETresume() + this is called when the user resumed the emulator. + + long NETqueryPlayer() + returns player number + + long NETsendPadData(void *pData, int Size) + this should be called for the first pad only on each side. + + long NETrecvPadData(void *pData, int Pad) + call this for Pad 1/2 to get the data sent by the above func. + + extended funcs: + + long NETsendData(void *pData, int Size, int Mode) + sends Size bytes from pData to the other side. + + long NETrecvData(void *pData, int Size, int Mode) + receives Size bytes from pData to the other side. + + void NETsetInfo(netInfo *info); + sets the netInfo struct. + + void NETkeypressed(int key) (linux only) + key is a XK_?? (X11) keycode. +*/ + +#ifdef __cplusplus +} +#endif +#endif // _PSEMU_PLUGIN_DEFS_H diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 88afba26..8277cb2b 100644..100755 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1,2838 +1,2838 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
- * Internal simulated HLE BIOS.
- */
-
-#include "psxbios.h"
-#include "psxhw.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 t8 (psxRegs.GPR.n.t8)
-#define t9 (psxRegs.GPR.n.t9)
-#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 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))
-
-typedef struct {
- u32 desc;
- s32 status;
- s32 mode;
- u32 fhandler;
-} EvCB[32];
-
-#define EvStUNUSED 0x0000
-#define EvStWAIT 0x1000
-#define EvStACTIVE 0x2000
-#define EvStALREADY 0x4000
-
-#define EvMdINTR 0x1000
-#define EvMdNOINTR 0x2000
-
-/*
-typedef struct {
- s32 next;
- s32 func1;
- s32 func2;
- s32 pad;
-} SysRPst;
-*/
-
-typedef struct {
- s32 status;
- s32 mode;
- u32 reg[32];
- u32 func;
-} TCB;
-
-typedef struct {
- u32 _pc0;
- u32 gp0;
- u32 t_addr;
- u32 t_size;
- u32 d_addr;
- u32 d_size;
- u32 b_addr;
- u32 b_size;
- u32 S_addr;
- u32 s_size;
- u32 _sp, _fp, _gp, ret, base;
-} EXEC;
-
-struct DIRENTRY {
- char name[20];
- s32 attr;
- s32 size;
- u32 next;
- s32 head;
- char system[4];
-};
-
-typedef struct {
- char name[32];
- u32 mode;
- u32 offset;
- u32 size;
- u32 mcfile;
-} FileDesc;
-
-static u32 *jmp_int = NULL;
-static int *pad_buf = NULL;
-static char *pad_buf1 = NULL, *pad_buf2 = NULL;
-static int pad_buf1len, pad_buf2len;
-
-static u32 regs[35];
-static EvCB *Event;
-static EvCB *HwEV; // 0xf0
-static EvCB *EvEV; // 0xf1
-static EvCB *RcEV; // 0xf2
-static EvCB *UeEV; // 0xf3
-static EvCB *SwEV; // 0xf4
-static EvCB *ThEV; // 0xff
-static u32 *heap_addr = NULL;
-static u32 *heap_end = NULL;
-static u32 SysIntRP[8];
-static int CardState = -1;
-static TCB Thread[8];
-static int CurThread = 0;
-static FileDesc FDesc[32];
-static u32 card_active_chan = 0;
-
-boolean hleSoftCall = FALSE;
-
-static inline void softCall(u32 pc) {
- pc0 = pc;
- ra = 0x80001000;
-
- hleSoftCall = TRUE;
-
- while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
-
- hleSoftCall = FALSE;
-}
-
-static inline void softCall2(u32 pc) {
- u32 sra = ra;
- pc0 = pc;
- ra = 0x80001000;
-
- hleSoftCall = TRUE;
-
- while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
- ra = sra;
-
- hleSoftCall = FALSE;
-}
-
-static inline void DeliverEvent(u32 ev, u32 spec) {
- if (Event[ev][spec].status != EvStACTIVE) return;
-
-// Event[ev][spec].status = EvStALREADY;
- if (Event[ev][spec].mode == EvMdINTR) {
- softCall2(Event[ev][spec].fhandler);
- } else Event[ev][spec].status = EvStALREADY;
-}
-
-static inline void SaveRegs() {
- memcpy(regs, psxRegs.GPR.r, 32*4);
- regs[32] = psxRegs.GPR.n.lo;
- regs[33] = psxRegs.GPR.n.hi;
- regs[34] = psxRegs.pc;
-}
-
-static inline void LoadRegs() {
- memcpy(psxRegs.GPR.r, regs, 32*4);
- psxRegs.GPR.n.lo = regs[32];
- psxRegs.GPR.n.hi = regs[33];
-}
-
-/* *
-// *
-// *
-// System calls A0 */
-
-
-void psxBios_abs() { // 0x0e
- if ((s32)a0 < 0) v0 = -(s32)a0;
- else v0 = a0;
- pc0 = ra;
-}
-
-void psxBios_labs() { // 0x0f
- psxBios_abs();
-}
-
-void psxBios_atoi() { // 0x10
- s32 n = 0, f = 0;
- char *p = (char *)Ra0;
-
- for (;;p++) {
- switch (*p) {
- case ' ': case '\t': continue;
- case '-': f++;
- case '+': p++;
- }
- break;
- }
-
- while (*p >= '0' && *p <= '9') {
- n = n * 10 + *p++ - '0';
- }
-
- v0 = (f ? -n : n);
- pc0 = ra;
-}
-
-void psxBios_atol() { // 0x11
- psxBios_atoi();
-}
-
-void psxBios_setjmp() { // 0x13
- u32 *jmp_buf = (u32 *)Ra0;
- int i;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
-#endif
-
- jmp_buf[0] = ra;
- jmp_buf[1] = sp;
- jmp_buf[2] = fp;
- for (i = 0; i < 8; i++) // s0-s7
- jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
- jmp_buf[11] = gp;
-
- v0 = 0; pc0 = ra;
-}
-
-void psxBios_longjmp() { // 0x14
- u32 *jmp_buf = (u32 *)Ra0;
- int i;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
-#endif
-
- ra = jmp_buf[0]; /* ra */
- sp = jmp_buf[1]; /* sp */
- fp = jmp_buf[2]; /* fp */
- for (i = 0; i < 8; i++) // s0-s7
- psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
- gp = jmp_buf[11]; /* gp */
-
- v0 = a1; pc0 = ra;
-}
-
-void psxBios_strcat() { // 0x15
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
-#endif
-
- while (*p1++);
- --p1;
- while ((*p1++ = *p2++) != '\0');
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_strncat() { // 0x16
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- s32 n = a2;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
-#endif
-
- while (*p1++);
- --p1;
- while ((*p1++ = *p2++) != '\0') {
- if (--n < 0) {
- *--p1 = '\0';
- break;
- }
- }
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_strcmp() { // 0x17
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
-#endif
-
- while (*p1 == *p2++) {
- if (*p1++ == '\0') {
- v0 = 0;
- pc0 = ra;
- return;
- }
- }
-
- v0 = (*p1 - *--p2);
- pc0 = ra;
-}
-
-void psxBios_strncmp() { // 0x18
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- s32 n = a2;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
-#endif
-
- while (--n >= 0 && *p1 == *p2++) {
- if (*p1++ == '\0') {
- v0 = 0;
- pc0 = ra;
- return;
- }
- }
-
- v0 = (n < 0 ? 0 : *p1 - *--p2);
- pc0 = ra;
-}
-
-void psxBios_strcpy() { // 0x19
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- while ((*p1++ = *p2++) != '\0');
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_strncpy() { // 0x1a
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- s32 n = a2, i;
-
- for (i = 0; i < n; i++) {
- if ((*p1++ = *p2++) == '\0') {
- while (++i < n) {
- *p1++ = '\0';
- }
- v0 = a0; pc0 = ra;
- return;
- }
- }
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_strlen() { // 0x1b
- char *p = (char *)Ra0;
- v0 = 0;
- while (*p++) v0++;
- pc0 = ra;
-}
-
-void psxBios_index() { // 0x1c
- char *p = (char *)Ra0;
-
- do {
- if (*p == a1) {
- v0 = a0 + (p - (char *)Ra0);
- pc0 = ra;
- return;
- }
- } while (*p++ != '\0');
-
- v0 = 0; pc0 = ra;
-}
-
-void psxBios_rindex() { // 0x1d
- char *p = (char *)Ra0;
-
- v0 = 0;
-
- do {
- if (*p == a1)
- v0 = a0 + (p - (char *)Ra0);
- } while (*p++ != '\0');
-
- pc0 = ra;
-}
-
-void psxBios_strchr() { // 0x1e
- psxBios_index();
-}
-
-void psxBios_strrchr() { // 0x1f
- psxBios_rindex();
-}
-
-void psxBios_strpbrk() { // 0x20
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
-
- while ((c = *p1++) != '\0') {
- for (scanp = p2; (sc = *scanp++) != '\0';) {
- if (sc == c) {
- v0 = a0 + (p1 - 1 - (char *)Ra0);
- pc0 = ra;
- return;
- }
- }
- }
-
- // BUG: return a0 instead of NULL if not found
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_strspn() { // 0x21
- char *p1, *p2;
-
- for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
- for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
- if (*p2 == '\0') break;
- }
-
- v0 = p1 - (char *)Ra0; pc0 = ra;
-}
-
-void psxBios_strcspn() { // 0x22
- char *p1, *p2;
-
- for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
- for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
- if (*p2 != '\0') break;
- }
-
- v0 = p1 - (char *)Ra0; pc0 = ra;
-}
-
-void psxBios_strtok() { // 0x23
- char *pcA0 = (char *)Ra0;
- char *pcRet = strtok(pcA0, (char *)Ra1);
- if (pcRet)
- v0 = a0 + pcRet - pcA0;
- else
- v0 = 0;
- pc0 = ra;
-}
-
-void psxBios_strstr() { // 0x24
- char *p = (char *)Ra0, *p1, *p2;
-
- while (*p != '\0') {
- p1 = p;
- p2 = (char *)Ra1;
-
- while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
- p1++; p2++;
- }
-
- if (*p2 == '\0') {
- v0 = a0 + (p - (char *)Ra0);
- pc0 = ra;
- return;
- }
-
- p++;
- }
-
- v0 = 0; pc0 = ra;
-}
-
-void psxBios_toupper() { // 0x25
- v0 = (s8)(a0 & 0xff);
- if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
- pc0 = ra;
-}
-
-void psxBios_tolower() { // 0x26
- v0 = (s8)(a0 & 0xff);
- if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
- pc0 = ra;
-}
-
-void psxBios_bcopy() { // 0x27
- char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
- while (a2-- > 0) *p1++ = *p2++;
-
- pc0 = ra;
-}
-
-void psxBios_bzero() { // 0x28
- char *p = (char *)Ra0;
- while (a1-- > 0) *p++ = '\0';
-
- pc0 = ra;
-}
-
-void psxBios_bcmp() { // 0x29
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-
- if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
-
- while (a2-- > 0) {
- if (*p1++ != *p2++) {
- v0 = *p1 - *p2; // BUG: compare the NEXT byte
- pc0 = ra;
- return;
- }
- }
-
- v0 = 0; pc0 = ra;
-}
-
-void psxBios_memcpy() { // 0x2a
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- while (a2-- > 0) *p1++ = *p2++;
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_memset() { // 0x2b
- char *p = (char *)Ra0;
- while (a2-- > 0) *p++ = (char)a1;
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_memmove() { // 0x2c
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-
- if (p2 <= p1 && p2 + a2 > p1) {
- a2++; // BUG: copy one more byte here
- p1 += a2;
- p2 += a2;
- while (a2-- > 0) *--p1 = *--p2;
- } else {
- while (a2-- > 0) *p1++ = *p2++;
- }
-
- v0 = a0; pc0 = ra;
-}
-
-void psxBios_memcmp() { // 0x2d
- psxBios_bcmp();
-}
-
-void psxBios_memchr() { // 0x2e
- char *p = (char *)Ra0;
-
- while (a2-- > 0) {
- if (*p++ != (s8)a1) continue;
- v0 = a0 + (p - (char *)Ra0 - 1);
- pc0 = ra;
- return;
- }
-
- v0 = 0; pc0 = ra;
-}
-
-void psxBios_rand() { // 0x2f
- u32 s = psxMu32(0x9010) * 1103515245 + 12345;
- v0 = (s >> 16) & 0x7fff;
- psxMu32ref(0x9010) = SWAPu32(s);
- pc0 = ra;
-}
-
-void psxBios_srand() { // 0x30
- psxMu32ref(0x9010) = SWAPu32(a0);
- pc0 = ra;
-}
-
-static u32 qscmpfunc, qswidth;
-
-static inline int qscmp(char *a, char *b) {
- u32 sa0 = a0;
-
- a0 = sa0 + (a - (char *)PSXM(sa0));
- a1 = sa0 + (b - (char *)PSXM(sa0));
-
- softCall2(qscmpfunc);
-
- a0 = sa0;
- return (s32)v0;
-}
-
-static inline void qexchange(char *i, char *j) {
- char t;
- int n = qswidth;
-
- do {
- t = *i;
- *i++ = *j;
- *j++ = t;
- } while (--n);
-}
-
-static inline void q3exchange(char *i, char *j, char *k) {
- char t;
- int n = qswidth;
-
- do {
- t = *i;
- *i++ = *k;
- *k++ = *j;
- *j++ = t;
- } while (--n);
-}
-
-static void qsort_main(char *a, char *l) {
- char *i, *j, *lp, *hp;
- int c;
- unsigned int n;
-
-start:
- if ((n = l - a) <= qswidth)
- return;
- n = qswidth * (n / (2 * qswidth));
- hp = lp = a + n;
- i = a;
- j = l - qswidth;
- while (TRUE) {
- if (i < lp) {
- if ((c = qscmp(i, lp)) == 0) {
- qexchange(i, lp -= qswidth);
- continue;
- }
- if (c < 0) {
- i += qswidth;
- continue;
- }
- }
-
-loop:
- if (j > hp) {
- if ((c = qscmp(hp, j)) == 0) {
- qexchange(hp += qswidth, j);
- goto loop;
- }
- if (c > 0) {
- if (i == lp) {
- q3exchange(i, hp += qswidth, j);
- i = lp += qswidth;
- goto loop;
- }
- qexchange(i, j);
- j -= qswidth;
- i += qswidth;
- continue;
- }
- j -= qswidth;
- goto loop;
- }
-
- if (i == lp) {
- if (lp - a >= l - hp) {
- qsort_main(hp + qswidth, l);
- l = lp;
- } else {
- qsort_main(a, lp);
- a = hp + qswidth;
- }
- goto start;
- }
-
- q3exchange(j, lp -= qswidth, i);
- j = hp -= qswidth;
- }
-}
-
-void psxBios_qsort() { // 0x31
- qswidth = a2;
- qscmpfunc = a3;
- qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
-
- pc0 = ra;
-}
-
-void psxBios_malloc() { // 0x33
- unsigned int *chunk, *newchunk;
- unsigned int dsize, csize, cstat;
- int colflag;
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
-#endif
-
- // scan through heap and combine free chunks of space
- chunk = heap_addr;
- colflag = 0;
- while(chunk < heap_end) {
- // get size and status of actual chunk
- csize = ((u32)*chunk) & 0xfffffffc;
- cstat = ((u32)*chunk) & 1;
-
- // it's a free chunk
- if(cstat == 1) {
- if(colflag == 0) {
- newchunk = chunk;
- dsize = csize;
- colflag = 1; // let's begin a new collection of free memory
- }
- else dsize += (csize+4); // add the new size including header
- }
- // not a free chunk: did we start a collection ?
- else {
- if(colflag == 1) { // collection is over
- colflag = 0;
- *newchunk = SWAP32(dsize | 1);
- }
- }
-
- // next chunk
- chunk = (u32*)((uptr)chunk + csize + 4);
- }
- // if neccessary free memory on end of heap
- if (colflag == 1)
- *newchunk = SWAP32(dsize | 1);
-
- chunk = heap_addr;
- csize = ((u32)*chunk) & 0xfffffffc;
- cstat = ((u32)*chunk) & 1;
- dsize = (a0 + 3) & 0xfffffffc;
-
- // exit on uninitialized heap
- if (chunk == NULL) {
- SysPrintf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
- v0 = 0;
- pc0 = ra;
- return;
- }
-
- // search an unused chunk that is big enough until the end of the heap
- while ((dsize > csize || cstat == 0) && chunk < heap_end ) {
- chunk = (u32*)((uptr)chunk + csize + 4);
- csize = ((u32)*chunk) & 0xfffffffc;
- cstat = ((u32)*chunk) & 1;
- }
-
- // catch out of memory
- if(chunk >= heap_end) { SysPrintf("malloc %x,%x: Out of memory error!\n", v0, a0); v0 = 0; pc0 = ra; return; }
-
- // allocate memory
- if(dsize == csize) {
- // chunk has same size
- *chunk &= 0xfffffffc;
- }
- else {
- // split free chunk
- *chunk = SWAP32(dsize);
- newchunk = (u32*)((uptr)chunk + dsize + 4);
- *newchunk = SWAP32((csize - dsize - 4) & 0xfffffffc | 1);
- }
-
- // return pointer to allocated memory
- v0 = ((unsigned long)chunk - (unsigned long)psxM) + 4;
- v0|= 0x80000000;
- SysPrintf ("malloc %x,%x\n", v0, a0);
- pc0 = ra;
-}
-
-void psxBios_free() { // 0x34
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
-#endif
-
- SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
-
- *(u32*)(Ra0-4) |= 1; // set chunk to free
- pc0 = ra;
-}
-
-void psxBios_calloc() { // 0x37
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
-#endif
-
- a0 = a0 * a1;
- psxBios_malloc();
- memset(Rv0, 0, a0);
-}
-
-void psxBios_realloc() { // 0x38
- u32 block = a0;
- u32 size = a1;
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
-#endif
-
- a0 = block;
- psxBios_free();
- a0 = size;
- psxBios_malloc();
-}
-
-
-/* InitHeap(void *block , int n) */
-void psxBios_InitHeap() { // 0x39
- unsigned int size;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
-#endif
-
- if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
- else size = a1;
-
- size &= 0xfffffffc;
-
- heap_addr = (u32 *)Ra0;
- heap_end = (u32 *)((u8 *)heap_addr + size);
- *heap_addr = SWAP32(size | 1);
-
- SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (uptr)heap_addr-(uptr)psxM, size);
-
- pc0 = ra;
-}
-
-void psxBios_getchar() { //0x3b
- v0 = getchar(); pc0 = ra;
-}
-
-void psxBios_printf() { // 0x3f
- char tmp[1024];
- char tmp2[1024];
- u32 save[4];
- char *ptmp = tmp;
- int n=1, i=0, j;
-
- memcpy(save, (char*)PSXM(sp), 4 * 4);
- psxMu32ref(sp) = SWAP32((u32)a0);
- psxMu32ref(sp + 4) = SWAP32((u32)a1);
- psxMu32ref(sp + 8) = SWAP32((u32)a2);
- psxMu32ref(sp + 12) = SWAP32((u32)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(tmp);
-
- pc0 = ra;
-}
-
-/*
- * long Load(char *name, struct EXEC *header);
- */
-
-void psxBios_Load() { // 0x42
- EXE_HEADER eheader;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
-#endif
-
- if (LoadCdromFile(Ra0, &eheader) == 0) {
- memcpy(Ra1, ((char*)&eheader)+16, sizeof(EXEC));
- v0 = 1;
- } else v0 = 0;
-
- pc0 = ra;
-}
-
-/*
- * int Exec(struct EXEC *header , int argc , char **argv);
- */
-
-void psxBios_Exec() { // 43
- EXEC *header = (EXEC*)Ra0;
- u32 tmp;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
-#endif
-
- header->_sp = sp;
- header->_fp = fp;
- header->_sp = sp;
- header->_gp = gp;
- header->ret = ra;
- header->base = s0;
-
- if (header->S_addr != 0) {
- tmp = header->S_addr + header->s_size;
- sp = tmp;
- fp = sp;
- }
-
- gp = header->gp0;
-
- s0 = a0;
-
- a0 = a1;
- a1 = a2;
-
- ra = 0x8000;
- pc0 = header->_pc0;
-}
-
-void psxBios_FlushCache() { // 44
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
-#endif
-
- psxRegs.ICache_valid = 0;
-
- pc0 = ra;
-}
-
-void psxBios_GPU_dw() { // 0x46
- int size;
- s32 *ptr;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
-#endif
-
- GPU_writeData(0xa0000000);
- GPU_writeData((a1<<16)|(a0&0xffff));
- GPU_writeData((a3<<16)|(a2&0xffff));
- size = (a2*a3+1)/2;
- ptr = (s32*)PSXM(Rsp[4]); //that is correct?
- do {
- GPU_writeData(SWAP32(*ptr));
- ptr++;
- } while(--size);
-
- pc0 = ra;
-}
-
-void psxBios_mem2vram() { // 0x47
- int size;
-
- GPU_writeData(0xa0000000);
- GPU_writeData((a1<<16)|(a0&0xffff));
- GPU_writeData((a3<<16)|(a2&0xffff));
- size = (a2*a3+1)/2;
- GPU_writeStatus(0x04000002);
- psxHwWrite32(0x1f8010f4,0);
- psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
- psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
- psxHwWrite32(0x1f8010a4,((size/16)<<16)|16);
- psxHwWrite32(0x1f8010a8,0x01000201);
-
- pc0 = ra;
-}
-
-void psxBios_SendGPU() { // 0x48
- GPU_writeStatus(a0);
- pc0 = ra;
-}
-
-void psxBios_GPU_cw() { // 0x49
- GPU_writeData(a0);
- pc0 = ra;
-}
-
-void psxBios_GPU_cwb() { // 0x4a
- s32 *ptr = (s32*)Ra0;
- int size = a1;
- while(size--) {
- GPU_writeData(SWAP32(*ptr));
- ptr++;
- }
-
- pc0 = ra;
-}
-
-void psxBios_GPU_SendPackets() { //4b:
- GPU_writeStatus(0x04000002);
- psxHwWrite32(0x1f8010f4,0);
- psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
- psxHwWrite32(0x1f8010a0,a0);
- psxHwWrite32(0x1f8010a4,0);
- psxHwWrite32(0x1f8010a8,0x010000401);
- pc0 = ra;
-}
-
-void psxBios_sys_a0_4c() { // 0x4c GPU relate
- psxHwWrite32(0x1f8010a8,0x00000401);
- GPU_writeData(0x0400000);
- GPU_writeData(0x0200000);
- GPU_writeData(0x0100000);
-
- pc0 = ra;
-}
-
-void psxBios_GPU_GetGPUStatus() { // 0x4d
- v0 = GPU_readStatus();
- pc0 = ra;
-}
-
-#undef s_addr
-
-void psxBios_LoadExec() { // 51
- EXEC *header = (EXEC*)PSXM(0xf000);
- u32 s_addr, s_size;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
-#endif
- s_addr = a1; s_size = a2;
-
- a1 = 0xf000;
- psxBios_Load();
-
- header->S_addr = s_addr;
- header->s_size = s_size;
-
- a0 = 0xf000; a1 = 0; a2 = 0;
- psxBios_Exec();
-}
-
-void psxBios__bu_init() { // 70
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
-#endif
-
- DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
- DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
-
- pc0 = ra;
-}
-
-void psxBios__96_init() { // 71
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
-#endif
-
- pc0 = ra;
-}
-
-void psxBios__96_remove() { // 72
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
-#endif
-
- pc0 = ra;
-}
-
-void psxBios_SetMem() { // 9f
- u32 new = psxHu32(0x1060);
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
-#endif
-
- switch(a0) {
- case 2:
- psxHu32ref(0x1060) = SWAP32(new);
- psxMu32ref(0x060) = a0;
- SysPrintf("Change effective memory : %d MBytes\n",a0);
- break;
-
- case 8:
- psxHu32ref(0x1060) = SWAP32(new | 0x300);
- psxMu32ref(0x060) = a0;
- SysPrintf("Change effective memory : %d MBytes\n",a0);
-
- default:
- SysPrintf("Effective memory must be 2/8 MBytes\n");
- break;
- }
-
- pc0 = ra;
-}
-
-void psxBios__card_info() { // ab
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
-#endif
-
- card_active_chan = a0;
-
-// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
- DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios__card_load() { // ac
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
-#endif
-
- card_active_chan = a0;
-
-// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
- DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
-
- v0 = 1; pc0 = ra;
-}
-
-/* System calls B0 */
-
-void psxBios_SetRCnt() { // 02
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
-#endif
-
- a0&= 0x3;
- if (a0 != 3) {
- u32 mode=0;
-
- psxRcntWtarget(a0, a1);
- if (a2&0x1000) mode|= 0x050; // Interrupt Mode
- if (a2&0x0100) mode|= 0x008; // Count to 0xffff
- if (a2&0x0010) mode|= 0x001; // Timer stop mode
- if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
- else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
-
- psxRcntWmode(a0, mode);
- }
- pc0 = ra;
-}
-
-void psxBios_GetRCnt() { // 03
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
-#endif
-
- a0&= 0x3;
- if (a0 != 3) v0 = psxRcntRcount(a0);
- else v0 = 0;
- pc0 = ra;
-}
-
-void psxBios_StartRCnt() { // 04
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
-#endif
-
- a0&= 0x3;
- if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
- else psxHu32ref(0x1074)|= SWAPu32(0x1);
- v0 = 1; pc0 = ra;
-}
-
-void psxBios_StopRCnt() { // 05
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
-#endif
-
- a0&= 0x3;
- if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
- else psxHu32ref(0x1074)&= SWAPu32(~0x1);
- pc0 = ra;
-}
-
-void psxBios_ResetRCnt() { // 06
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
-#endif
-
- a0&= 0x3;
- if (a0 != 3) {
- psxRcntWmode(a0, 0);
- psxRcntWtarget(a0, 0);
- psxRcntWcount(a0, 0);
- }
- pc0 = ra;
-}
-
-
-/* gets ev for use with Event */
-#define GetEv() \
- ev = (a0 >> 24) & 0xf; \
- if (ev == 0xf) ev = 0x5; \
- ev*= 32; \
- ev+= a0&0x1f;
-
-/* gets spec for use with Event */
-#define GetSpec() \
- spec = 0; \
- switch (a1) { \
- case 0x0301: spec = 16; break; \
- case 0x0302: spec = 17; break; \
- default: \
- for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
- break; \
- }
-
-void psxBios_DeliverEvent() { // 07
- int ev, spec;
- int i;
-
- GetEv();
- GetSpec();
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
-#endif
-
- DeliverEvent(ev, spec);
-
- pc0 = ra;
-}
-
-void psxBios_OpenEvent() { // 08
- int ev, spec;
- int i;
-
- GetEv();
- GetSpec();
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
-#endif
-
- Event[ev][spec].status = EvStWAIT;
- Event[ev][spec].mode = a2;
- Event[ev][spec].fhandler = a3;
-
- v0 = ev | (spec << 8);
- pc0 = ra;
-}
-
-void psxBios_CloseEvent() { // 09
- int ev, spec;
-
- ev = a0 & 0xff;
- spec = (a0 >> 8) & 0xff;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
-#endif
-
- Event[ev][spec].status = EvStUNUSED;
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios_WaitEvent() { // 0a
- int ev, spec;
-
- ev = a0 & 0xff;
- spec = (a0 >> 8) & 0xff;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
-#endif
-
- Event[ev][spec].status = EvStACTIVE;
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios_TestEvent() { // 0b
- int ev, spec;
-
- ev = a0 & 0xff;
- spec = (a0 >> 8) & 0xff;
-
- if (Event[ev][spec].status == EvStALREADY) {
- Event[ev][spec].status = EvStACTIVE; v0 = 1;
- } else v0 = 0;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
-#endif
-
- pc0 = ra;
-}
-
-void psxBios_EnableEvent() { // 0c
- int ev, spec;
-
- ev = a0 & 0xff;
- spec = (a0 >> 8) & 0xff;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
-#endif
-
- Event[ev][spec].status = EvStACTIVE;
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios_DisableEvent() { // 0d
- int ev, spec;
-
- ev = a0 & 0xff;
- spec = (a0 >> 8) & 0xff;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
-#endif
-
- Event[ev][spec].status = EvStWAIT;
-
- v0 = 1; pc0 = ra;
-}
-
-/*
- * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
- */
-
-void psxBios_OpenTh() { // 0e
- int th;
-
- for (th=1; th<8; th++)
- if (Thread[th].status == 0) break;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
-#endif
-
- Thread[th].status = 1;
- Thread[th].func = a0;
- Thread[th].reg[29] = a1;
- Thread[th].reg[28] = a2;
-
- v0 = th; pc0 = ra;
-}
-
-/*
- * int CloseTh(long thread);
- */
-
-void psxBios_CloseTh() { // 0f
- int th = a0 & 0xff;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
-#endif
-
- if (Thread[th].status == 0) {
- v0 = 0;
- } else {
- Thread[th].status = 0;
- v0 = 1;
- }
-
- pc0 = ra;
-}
-
-/*
- * int ChangeTh(long thread);
- */
-
-void psxBios_ChangeTh() { // 10
- int th = a0 & 0xff;
-
-#ifdef PSXBIOS_LOG
-// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
-#endif
-
- if (Thread[th].status == 0 || CurThread == th) {
- v0 = 0;
-
- pc0 = ra;
- } else {
- v0 = 1;
-
- if (Thread[CurThread].status == 2) {
- Thread[CurThread].status = 1;
- Thread[CurThread].func = ra;
- memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
- }
-
- memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
- pc0 = Thread[th].func;
- Thread[th].status = 2;
- CurThread = th;
- }
-}
-
-void psxBios_InitPAD() { // 0x12
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
-#endif
-
- pad_buf1 = (char*)Ra0;
- pad_buf1len = a1;
- pad_buf2 = (char*)Ra2;
- pad_buf2len = a3;
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios_StartPAD() { // 13
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
-#endif
-
- psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
- psxRegs.CP0.n.Status |= 0x401;
- pc0 = ra;
-}
-
-void psxBios_StopPAD() { // 14
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
-#endif
-
- pad_buf1 = NULL;
- pad_buf2 = NULL;
- pc0 = ra;
-}
-
-void psxBios_PAD_init() { // 15
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
-#endif
- psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
- pad_buf = (int *)Ra1;
- *pad_buf = -1;
- psxRegs.CP0.n.Status |= 0x401;
- pc0 = ra;
-}
-
-void psxBios_PAD_dr() { // 16
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
-#endif
-
- v0 = -1; pc0 = ra;
-}
-
-void psxBios_ReturnFromException() { // 17
- LoadRegs();
-
- pc0 = psxRegs.CP0.n.EPC;
- if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
-
- psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
- ((psxRegs.CP0.n.Status & 0x3c) >> 2);
-}
-
-void psxBios_ResetEntryInt() { // 18
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
-#endif
-
- jmp_int = NULL;
- pc0 = ra;
-}
-
-void psxBios_HookEntryInt() { // 19
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
-#endif
-
- jmp_int = (u32*)Ra0;
- pc0 = ra;
-}
-
-void psxBios_UnDeliverEvent() { // 0x20
- int ev, spec;
- int i;
-
- GetEv();
- GetSpec();
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
-#endif
-
- if (Event[ev][spec].status == EvStALREADY &&
- Event[ev][spec].mode == EvMdNOINTR)
- Event[ev][spec].status = EvStACTIVE;
-
- pc0 = ra;
-}
-
-#define buopen(mcd) { \
- strcpy(FDesc[1 + mcd].name, Ra0+5); \
- FDesc[1 + mcd].offset = 0; \
- FDesc[1 + mcd].mode = a1; \
- \
- for (i=1; i<16; i++) { \
- ptr = Mcd##mcd##Data + 128 * i; \
- if ((*ptr & 0xF0) != 0x50) continue; \
- if (strcmp(FDesc[1 + mcd].name, ptr+0xa)) continue; \
- FDesc[1 + mcd].mcfile = i; \
- SysPrintf("open %s\n", ptr+0xa); \
- v0 = 1 + mcd; \
- break; \
- } \
- if (a1 & 0x200 && v0 == -1) { /* FCREAT */ \
- for (i=1; i<16; i++) { \
- int j, xor = 0; \
- \
- ptr = Mcd##mcd##Data + 128 * i; \
- if ((*ptr & 0xF0) == 0x50) continue; \
- ptr[0] = 0x50 | (u8)(a1 >> 16); \
- ptr[4] = 0x00; \
- ptr[5] = 0x20; \
- ptr[6] = 0x00; \
- ptr[7] = 0x00; \
- ptr[8] = 'B'; \
- ptr[9] = 'I'; \
- strcpy(ptr+0xa, FDesc[1 + mcd].name); \
- for (j=0; j<127; j++) xor^= ptr[j]; \
- ptr[127] = xor; \
- FDesc[1 + mcd].mcfile = i; \
- SysPrintf("openC %s\n", ptr); \
- v0 = 1 + mcd; \
- SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 128); \
- break; \
- } \
- } \
-}
-
-/*
- * int open(char *name , int mode);
- */
-
-void psxBios_open() { // 0x32
- int i;
- char *ptr;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
-#endif
-
- v0 = -1;
-
- if (!strncmp(Ra0, "bu00", 4)) {
- buopen(1);
- }
-
- if (!strncmp(Ra0, "bu10", 4)) {
- buopen(2);
- }
-
- pc0 = ra;
-}
-
-/*
- * int lseek(int fd , int offset , int whence);
- */
-
-void psxBios_lseek() { // 0x33
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
-#endif
-
- switch (a2) {
- case 0: // SEEK_SET
- FDesc[a0].offset = a1;
- v0 = a1;
-// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
-// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
- break;
-
- case 1: // SEEK_CUR
- FDesc[a0].offset+= a1;
- v0 = FDesc[a0].offset;
- break;
- }
-
- pc0 = ra;
-}
-
-#define buread(mcd) { \
- SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
- ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
- memcpy(Ra1, ptr, a2); \
- if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \
- else v0 = a2; \
- FDesc[1 + mcd].offset += v0; \
- DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
- DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
-}
-
-/*
- * int read(int fd , void *buf , int nbytes);
- */
-
-void psxBios_read() { // 0x34
- char *ptr;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
-#endif
-
- v0 = -1;
-
- switch (a0) {
- case 2: buread(1); break;
- case 3: buread(2); break;
- }
-
- pc0 = ra;
-}
-
-#define buwrite(mcd) { \
- u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
- SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
- ptr = Mcd##mcd##Data + offset; \
- memcpy(ptr, Ra1, a2); \
- FDesc[1 + mcd].offset += a2; \
- SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, a2); \
- if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \
- else v0 = a2; \
- DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
- DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
-}
-
-/*
- * int write(int fd , void *buf , int nbytes);
- */
-
-void psxBios_write() { // 0x35/0x03
- char *ptr;
-
- if (a0 == 1) { // stdout
- char *ptr = Ra1;
-
- while (a2 > 0) {
- SysPrintf("%c", *ptr++); a2--;
- }
- pc0 = ra; return;
- }
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
-#endif
-
- v0 = -1;
-
- switch (a0) {
- case 2: buwrite(1); break;
- case 3: buwrite(2); break;
- }
-
- pc0 = ra;
-}
-
-/*
- * int close(int fd);
- */
-
-void psxBios_close() { // 0x36
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
-#endif
-
- v0 = a0;
- pc0 = ra;
-}
-
-void psxBios_putchar() { // 3d
- SysPrintf("%c", (char)a0);
- pc0 = ra;
-}
-
-void psxBios_puts() { // 3e/3f
- SysPrintf(Ra0);
- pc0 = ra;
-}
-
-char ffile[64], *pfile;
-int nfile;
-
-#define bufile(mcd) { \
- while (nfile < 16) { \
- int match=1; \
- \
- ptr = Mcd##mcd##Data + 128 * nfile; \
- nfile++; \
- if ((*ptr & 0xF0) != 0x50) continue; \
- ptr+= 0xa; \
- if (pfile[0] == 0) { \
- strcpy(dir->name, ptr); \
- } else for (i=0; i<20; i++) { \
- if (pfile[i] == ptr[i]) { \
- dir->name[i] = ptr[i]; \
- if (ptr[i] == 0) break; else continue; } \
- if (pfile[i] == '?') { \
- dir->name[i] = ptr[i]; continue; } \
- if (pfile[i] == '*') { \
- strcpy(dir->name+i, ptr+i); break; } \
- match = 0; break; \
- } \
- SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
- if (match == 0) continue; \
- dir->size = 8192; \
- v0 = _dir; \
- break; \
- } \
-}
-
-/*
- * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
- */
-
-void psxBios_firstfile() { // 42
- struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
- u32 _dir = a1;
- char *ptr;
- int i;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
-#endif
-
- v0 = 0;
-
- strcpy(ffile, Ra0);
- pfile = ffile+5;
- nfile = 1;
- if (!strncmp(Ra0, "bu00", 4)) {
- bufile(1);
- } else if (!strncmp(Ra0, "bu10", 4)) {
- bufile(2);
- }
-
- // firstfile() calls _card_read() internally, so deliver it's event
- DeliverEvent(0x11, 0x2);
-
- pc0 = ra;
-}
-
-/*
- * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
- */
-
-void psxBios_nextfile() { // 43
- struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
- u32 _dir = a0;
- char *ptr;
- int i;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
-#endif
-
- v0 = 0;
-
- if (!strncmp(ffile, "bu00", 4)) {
- bufile(1);
- }
-
- if (!strncmp(ffile, "bu10", 4)) {
- bufile(2);
- }
-
- pc0 = ra;
-}
-
-#define burename(mcd) { \
- for (i=1; i<16; i++) { \
- int namelen, j, xor = 0; \
- ptr = Mcd##mcd##Data + 128 * i; \
- if ((*ptr & 0xF0) != 0x50) continue; \
- if (strcmp(Ra0+5, ptr+0xa)) continue; \
- namelen = strlen(Ra1+5); \
- memcpy(ptr+0xa, Ra1+5, namelen); \
- memset(ptr+0xa+namelen, 0, 0x75-namelen); \
- for (j=0; j<127; j++) xor^= ptr[j]; \
- ptr[127] = xor; \
- SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
- v0 = 1; \
- break; \
- } \
-}
-
-/*
- * int rename(char *old, char *new);
- */
-
-void psxBios_rename() { // 44
- char *ptr;
- int i;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
-#endif
-
- v0 = 0;
-
- if (!strncmp(Ra0, "bu00", 4) && !strncmp(Ra1, "bu00", 4)) {
- burename(1);
- }
-
- if (!strncmp(Ra0, "bu10", 4) && !strncmp(Ra1, "bu10", 4)) {
- burename(2);
- }
-
- pc0 = ra;
-}
-
-
-#define budelete(mcd) { \
- for (i=1; i<16; i++) { \
- ptr = Mcd##mcd##Data + 128 * i; \
- if ((*ptr & 0xF0) != 0x50) continue; \
- if (strcmp(Ra0+5, ptr+0xa)) continue; \
- *ptr = (*ptr & 0xf) | 0xA0; \
- SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
- SysPrintf("delete %s\n", ptr+0xa); \
- v0 = 1; \
- break; \
- } \
-}
-
-/*
- * int delete(char *name);
- */
-
-void psxBios_delete() { // 45
- char *ptr;
- int i;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
-#endif
-
- v0 = 0;
-
- if (!strncmp(Ra0, "bu00", 4)) {
- budelete(1);
- }
-
- if (!strncmp(Ra0, "bu10", 4)) {
- budelete(2);
- }
-
- pc0 = ra;
-}
-
-void psxBios_InitCARD() { // 4a
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
-#endif
-
- CardState = 0;
-
- pc0 = ra;
-}
-
-void psxBios_StartCARD() { // 4b
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
-#endif
-
- if (CardState == 0) CardState = 1;
-
- pc0 = ra;
-}
-
-void psxBios_StopCARD() { // 4c
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
-#endif
-
- if (CardState == 1) CardState = 0;
-
- pc0 = ra;
-}
-
-void psxBios__card_write() { // 0x4e
- int port;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
-#endif
-
- card_active_chan = a0;
- port = a0 >> 4;
-
- if (port == 0) {
- memcpy(Mcd1Data + a1 * 128, Ra2, 128);
- SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
- } else {
- memcpy(Mcd2Data + a1 * 128, Ra2, 128);
- SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
- }
-
- DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
-// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios__card_read() { // 0x4f
- int port;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
-#endif
-
- card_active_chan = a0;
- port = a0 >> 4;
-
- if (port == 0) {
- memcpy(Ra2, Mcd1Data + a1 * 128, 128);
- } else {
- memcpy(Ra2, Mcd2Data + a1 * 128, 128);
- }
-
- DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
-// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
-
- v0 = 1; pc0 = ra;
-}
-
-void psxBios__new_card() { // 0x50
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
-#endif
-
- pc0 = ra;
-}
-
-void psxBios_Krom2RawAdd() { // 0x51
- int i = 0;
-
- const u32 table_8140[][2] = {
- {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
- {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
- {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
- {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
- {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
- {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
- {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
- {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
- {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
- {0xffff, 0}
- };
-
- const u32 table_889f[][2] = {
- {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
- {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
- {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
- {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
- {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
- {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
- {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
- {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
- {0xffff, 0}
- };
-
- if (a0 >= 0x8140 && a0 <= 0x84be) {
- while (table_8140[i][0] <= a0) i++;
- a0 -= table_8140[i - 1][0];
- v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
- } else if (a0 >= 0x889f && a0 <= 0x9872) {
- while (table_889f[i][0] <= a0) i++;
- a0 -= table_889f[i - 1][0];
- v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
- } else {
- v0 = 0xffffffff;
- }
-
- pc0 = ra;
-}
-
-void psxBios_GetC0Table() { // 56
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
-#endif
-
- v0 = 0x674; pc0 = ra;
-}
-
-void psxBios_GetB0Table() { // 57
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
-#endif
-
- v0 = 0x874; pc0 = ra;
-}
-
-void psxBios__card_chan() { // 0x58
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
-#endif
-
- v0 = card_active_chan;
- pc0 = ra;
-}
-
-void psxBios_ChangeClearPad() { // 5b
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
-#endif
-
- pc0 = ra;
-}
-
-/* System calls C0 */
-
-/*
- * int SysEnqIntRP(int index , long *queue);
- */
-
-void psxBios_SysEnqIntRP() { // 02
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
-#endif
-
- SysIntRP[a0] = a1;
-
- v0 = 0; pc0 = ra;
-}
-
-/*
- * int SysDeqIntRP(int index , long *queue);
- */
-
-void psxBios_SysDeqIntRP() { // 03
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
-#endif
-
- SysIntRP[a0] = 0;
-
- v0 = 0; pc0 = ra;
-}
-
-void psxBios_ChangeClearRCnt() { // 0a
- u32 *ptr;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
-#endif
-
- ptr = (u32*)PSXM((a0 << 2) + 0x8600);
- v0 = *ptr;
- *ptr = a1;
-
-// psxRegs.CP0.n.Status|= 0x404;
- pc0 = ra;
-}
-
-void psxBios_dummy() {
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
-#endif
- pc0 = ra;
-}
-
-void (*biosA0[256])();
-void (*biosB0[256])();
-void (*biosC0[256])();
-
-#include "sjisfont.h"
-
-void psxBiosInit() {
- u32 base, size;
- u32 *ptr;
- int i;
- uLongf len;
-
- for(i = 0; i < 256; i++) {
- biosA0[i] = NULL;
- biosB0[i] = NULL;
- biosC0[i] = NULL;
- }
- biosA0[0x3e] = psxBios_puts;
- biosA0[0x3f] = psxBios_printf;
-
- biosB0[0x3d] = psxBios_putchar;
- biosB0[0x3f] = psxBios_puts;
-
- if (!Config.HLE) return;
-
- for(i = 0; i < 256; i++) {
- if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
- if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
- if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
- }
-
- biosA0[0x00] = psxBios_open;
- biosA0[0x01] = psxBios_lseek;
- biosA0[0x02] = psxBios_read;
- biosA0[0x03] = psxBios_write;
- biosA0[0x04] = psxBios_close;
- //biosA0[0x05] = psxBios_ioctl;
- //biosA0[0x06] = psxBios_exit;
- //biosA0[0x07] = psxBios_sys_a0_07;
- //biosA0[0x08] = psxBios_getc;
- //biosA0[0x09] = psxBios_putc;
- //biosA0[0x0a] = psxBios_todigit;
- //biosA0[0x0b] = psxBios_atof;
- //biosA0[0x0c] = psxBios_strtoul;
- //biosA0[0x0d] = psxBios_strtol;
- biosA0[0x0e] = psxBios_abs;
- biosA0[0x0f] = psxBios_labs;
- biosA0[0x10] = psxBios_atoi;
- biosA0[0x11] = psxBios_atol;
- //biosA0[0x12] = psxBios_atob;
- biosA0[0x13] = psxBios_setjmp;
- biosA0[0x14] = psxBios_longjmp;
- biosA0[0x15] = psxBios_strcat;
- biosA0[0x16] = psxBios_strncat;
- biosA0[0x17] = psxBios_strcmp;
- biosA0[0x18] = psxBios_strncmp;
- biosA0[0x19] = psxBios_strcpy;
- biosA0[0x1a] = psxBios_strncpy;
- biosA0[0x1b] = psxBios_strlen;
- biosA0[0x1c] = psxBios_index;
- biosA0[0x1d] = psxBios_rindex;
- biosA0[0x1e] = psxBios_strchr;
- biosA0[0x1f] = psxBios_strrchr;
- biosA0[0x20] = psxBios_strpbrk;
- biosA0[0x21] = psxBios_strspn;
- biosA0[0x22] = psxBios_strcspn;
- biosA0[0x23] = psxBios_strtok;
- biosA0[0x24] = psxBios_strstr;
- biosA0[0x25] = psxBios_toupper;
- biosA0[0x26] = psxBios_tolower;
- biosA0[0x27] = psxBios_bcopy;
- biosA0[0x28] = psxBios_bzero;
- biosA0[0x29] = psxBios_bcmp;
- biosA0[0x2a] = psxBios_memcpy;
- biosA0[0x2b] = psxBios_memset;
- biosA0[0x2c] = psxBios_memmove;
- biosA0[0x2d] = psxBios_memcmp;
- biosA0[0x2e] = psxBios_memchr;
- biosA0[0x2f] = psxBios_rand;
- biosA0[0x30] = psxBios_srand;
- biosA0[0x31] = psxBios_qsort;
- //biosA0[0x32] = psxBios_strtod;
- biosA0[0x33] = psxBios_malloc;
- biosA0[0x34] = psxBios_free;
- //biosA0[0x35] = psxBios_lsearch;
- //biosA0[0x36] = psxBios_bsearch;
- biosA0[0x37] = psxBios_calloc;
- biosA0[0x38] = psxBios_realloc;
- biosA0[0x39] = psxBios_InitHeap;
- //biosA0[0x3a] = psxBios__exit;
- biosA0[0x3b] = psxBios_getchar;
- biosA0[0x3c] = psxBios_putchar;
- //biosA0[0x3d] = psxBios_gets;
- //biosA0[0x40] = psxBios_sys_a0_40;
- //biosA0[0x41] = psxBios_LoadTest;
- biosA0[0x42] = psxBios_Load;
- biosA0[0x43] = psxBios_Exec;
- biosA0[0x44] = psxBios_FlushCache;
- //biosA0[0x45] = psxBios_InstallInterruptHandler;
- biosA0[0x46] = psxBios_GPU_dw;
- biosA0[0x47] = psxBios_mem2vram;
- biosA0[0x48] = psxBios_SendGPU;
- biosA0[0x49] = psxBios_GPU_cw;
- biosA0[0x4a] = psxBios_GPU_cwb;
- biosA0[0x4b] = psxBios_GPU_SendPackets;
- biosA0[0x4c] = psxBios_sys_a0_4c;
- biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
- //biosA0[0x4e] = psxBios_GPU_sync;
- //biosA0[0x4f] = psxBios_sys_a0_4f;
- //biosA0[0x50] = psxBios_sys_a0_50;
- biosA0[0x51] = psxBios_LoadExec;
- //biosA0[0x52] = psxBios_GetSysSp;
- //biosA0[0x53] = psxBios_sys_a0_53;
- //biosA0[0x54] = psxBios__96_init_a54;
- //biosA0[0x55] = psxBios__bu_init_a55;
- //biosA0[0x56] = psxBios__96_remove_a56;
- //biosA0[0x57] = psxBios_sys_a0_57;
- //biosA0[0x58] = psxBios_sys_a0_58;
- //biosA0[0x59] = psxBios_sys_a0_59;
- //biosA0[0x5a] = psxBios_sys_a0_5a;
- //biosA0[0x5b] = psxBios_dev_tty_init;
- //biosA0[0x5c] = psxBios_dev_tty_open;
- //biosA0[0x5d] = psxBios_sys_a0_5d;
- //biosA0[0x5e] = psxBios_dev_tty_ioctl;
- //biosA0[0x5f] = psxBios_dev_cd_open;
- //biosA0[0x60] = psxBios_dev_cd_read;
- //biosA0[0x61] = psxBios_dev_cd_close;
- //biosA0[0x62] = psxBios_dev_cd_firstfile;
- //biosA0[0x63] = psxBios_dev_cd_nextfile;
- //biosA0[0x64] = psxBios_dev_cd_chdir;
- //biosA0[0x65] = psxBios_dev_card_open;
- //biosA0[0x66] = psxBios_dev_card_read;
- //biosA0[0x67] = psxBios_dev_card_write;
- //biosA0[0x68] = psxBios_dev_card_close;
- //biosA0[0x69] = psxBios_dev_card_firstfile;
- //biosA0[0x6a] = psxBios_dev_card_nextfile;
- //biosA0[0x6b] = psxBios_dev_card_erase;
- //biosA0[0x6c] = psxBios_dev_card_undelete;
- //biosA0[0x6d] = psxBios_dev_card_format;
- //biosA0[0x6e] = psxBios_dev_card_rename;
- //biosA0[0x6f] = psxBios_dev_card_6f;
- biosA0[0x70] = psxBios__bu_init;
- biosA0[0x71] = psxBios__96_init;
- biosA0[0x72] = psxBios__96_remove;
- //biosA0[0x73] = psxBios_sys_a0_73;
- //biosA0[0x74] = psxBios_sys_a0_74;
- //biosA0[0x75] = psxBios_sys_a0_75;
- //biosA0[0x76] = psxBios_sys_a0_76;
- //biosA0[0x77] = psxBios_sys_a0_77;
- //biosA0[0x78] = psxBios__96_CdSeekL;
- //biosA0[0x79] = psxBios_sys_a0_79;
- //biosA0[0x7a] = psxBios_sys_a0_7a;
- //biosA0[0x7b] = psxBios_sys_a0_7b;
- //biosA0[0x7c] = psxBios__96_CdGetStatus;
- //biosA0[0x7d] = psxBios_sys_a0_7d;
- //biosA0[0x7e] = psxBios__96_CdRead;
- //biosA0[0x7f] = psxBios_sys_a0_7f;
- //biosA0[0x80] = psxBios_sys_a0_80;
- //biosA0[0x81] = psxBios_sys_a0_81;
- //biosA0[0x82] = psxBios_sys_a0_82;
- //biosA0[0x83] = psxBios_sys_a0_83;
- //biosA0[0x84] = psxBios_sys_a0_84;
- //biosA0[0x85] = psxBios__96_CdStop;
- //biosA0[0x86] = psxBios_sys_a0_86;
- //biosA0[0x87] = psxBios_sys_a0_87;
- //biosA0[0x88] = psxBios_sys_a0_88;
- //biosA0[0x89] = psxBios_sys_a0_89;
- //biosA0[0x8a] = psxBios_sys_a0_8a;
- //biosA0[0x8b] = psxBios_sys_a0_8b;
- //biosA0[0x8c] = psxBios_sys_a0_8c;
- //biosA0[0x8d] = psxBios_sys_a0_8d;
- //biosA0[0x8e] = psxBios_sys_a0_8e;
- //biosA0[0x8f] = psxBios_sys_a0_8f;
- //biosA0[0x90] = psxBios_sys_a0_90;
- //biosA0[0x91] = psxBios_sys_a0_91;
- //biosA0[0x92] = psxBios_sys_a0_92;
- //biosA0[0x93] = psxBios_sys_a0_93;
- //biosA0[0x94] = psxBios_sys_a0_94;
- //biosA0[0x95] = psxBios_sys_a0_95;
- //biosA0[0x96] = psxBios_AddCDROMDevice;
- //biosA0[0x97] = psxBios_AddMemCardDevide;
- //biosA0[0x98] = psxBios_DisableKernelIORedirection;
- //biosA0[0x99] = psxBios_EnableKernelIORedirection;
- //biosA0[0x9a] = psxBios_sys_a0_9a;
- //biosA0[0x9b] = psxBios_sys_a0_9b;
- //biosA0[0x9c] = psxBios_SetConf;
- //biosA0[0x9d] = psxBios_GetConf;
- //biosA0[0x9e] = psxBios_sys_a0_9e;
- biosA0[0x9f] = psxBios_SetMem;
- //biosA0[0xa0] = psxBios__boot;
- //biosA0[0xa1] = psxBios_SystemError;
- //biosA0[0xa2] = psxBios_EnqueueCdIntr;
- //biosA0[0xa3] = psxBios_DequeueCdIntr;
- //biosA0[0xa4] = psxBios_sys_a0_a4;
- //biosA0[0xa5] = psxBios_ReadSector;
- //biosA0[0xa6] = psxBios_get_cd_status;
- //biosA0[0xa7] = psxBios_bufs_cb_0;
- //biosA0[0xa8] = psxBios_bufs_cb_1;
- //biosA0[0xa9] = psxBios_bufs_cb_2;
- //biosA0[0xaa] = psxBios_bufs_cb_3;
- biosA0[0xab] = psxBios__card_info;
- biosA0[0xac] = psxBios__card_load;
- //biosA0[0axd] = psxBios__card_auto;
- //biosA0[0xae] = psxBios_bufs_cd_4;
- //biosA0[0xaf] = psxBios_sys_a0_af;
- //biosA0[0xb0] = psxBios_sys_a0_b0;
- //biosA0[0xb1] = psxBios_sys_a0_b1;
- //biosA0[0xb2] = psxBios_do_a_long_jmp
- //biosA0[0xb3] = psxBios_sys_a0_b3;
- //biosA0[0xb4] = psxBios_sub_function;
-//*******************B0 CALLS****************************
- //biosB0[0x00] = psxBios_SysMalloc;
- //biosB0[0x01] = psxBios_sys_b0_01;
- biosB0[0x02] = psxBios_SetRCnt;
- biosB0[0x03] = psxBios_GetRCnt;
- biosB0[0x04] = psxBios_StartRCnt;
- biosB0[0x05] = psxBios_StopRCnt;
- biosB0[0x06] = psxBios_ResetRCnt;
- biosB0[0x07] = psxBios_DeliverEvent;
- biosB0[0x08] = psxBios_OpenEvent;
- biosB0[0x09] = psxBios_CloseEvent;
- biosB0[0x0a] = psxBios_WaitEvent;
- biosB0[0x0b] = psxBios_TestEvent;
- biosB0[0x0c] = psxBios_EnableEvent;
- biosB0[0x0d] = psxBios_DisableEvent;
- biosB0[0x0e] = psxBios_OpenTh;
- biosB0[0x0f] = psxBios_CloseTh;
- biosB0[0x10] = psxBios_ChangeTh;
- //biosB0[0x11] = psxBios_psxBios_b0_11;
- biosB0[0x12] = psxBios_InitPAD;
- biosB0[0x13] = psxBios_StartPAD;
- biosB0[0x14] = psxBios_StopPAD;
- biosB0[0x15] = psxBios_PAD_init;
- biosB0[0x16] = psxBios_PAD_dr;
- biosB0[0x17] = psxBios_ReturnFromException;
- biosB0[0x18] = psxBios_ResetEntryInt;
- biosB0[0x19] = psxBios_HookEntryInt;
- //biosB0[0x1a] = psxBios_sys_b0_1a;
- //biosB0[0x1b] = psxBios_sys_b0_1b;
- //biosB0[0x1c] = psxBios_sys_b0_1c;
- //biosB0[0x1d] = psxBios_sys_b0_1d;
- //biosB0[0x1e] = psxBios_sys_b0_1e;
- //biosB0[0x1f] = psxBios_sys_b0_1f;
- biosB0[0x20] = psxBios_UnDeliverEvent;
- //biosB0[0x21] = psxBios_sys_b0_21;
- //biosB0[0x22] = psxBios_sys_b0_22;
- //biosB0[0x23] = psxBios_sys_b0_23;
- //biosB0[0x24] = psxBios_sys_b0_24;
- //biosB0[0x25] = psxBios_sys_b0_25;
- //biosB0[0x26] = psxBios_sys_b0_26;
- //biosB0[0x27] = psxBios_sys_b0_27;
- //biosB0[0x28] = psxBios_sys_b0_28;
- //biosB0[0x29] = psxBios_sys_b0_29;
- //biosB0[0x2a] = psxBios_sys_b0_2a;
- //biosB0[0x2b] = psxBios_sys_b0_2b;
- //biosB0[0x2c] = psxBios_sys_b0_2c;
- //biosB0[0x2d] = psxBios_sys_b0_2d;
- //biosB0[0x2e] = psxBios_sys_b0_2e;
- //biosB0[0x2f] = psxBios_sys_b0_2f;
- //biosB0[0x30] = psxBios_sys_b0_30;
- //biosB0[0x31] = psxBios_sys_b0_31;
- biosB0[0x32] = psxBios_open;
- biosB0[0x33] = psxBios_lseek;
- biosB0[0x34] = psxBios_read;
- biosB0[0x35] = psxBios_write;
- biosB0[0x36] = psxBios_close;
- //biosB0[0x37] = psxBios_ioctl;
- //biosB0[0x38] = psxBios_exit;
- //biosB0[0x39] = psxBios_sys_b0_39;
- //biosB0[0x3a] = psxBios_getc;
- //biosB0[0x3b] = psxBios_putc;
- biosB0[0x3c] = psxBios_getchar;
- //biosB0[0x3e] = psxBios_gets;
- //biosB0[0x40] = psxBios_cd;
- //biosB0[0x41] = psxBios_format;
- biosB0[0x42] = psxBios_firstfile;
- biosB0[0x43] = psxBios_nextfile;
- biosB0[0x44] = psxBios_rename;
- biosB0[0x45] = psxBios_delete;
- //biosB0[0x46] = psxBios_undelete;
- //biosB0[0x47] = psxBios_AddDevice;
- //biosB0[0x48] = psxBios_RemoteDevice;
- //biosB0[0x49] = psxBios_PrintInstalledDevices;
- biosB0[0x4a] = psxBios_InitCARD;
- biosB0[0x4b] = psxBios_StartCARD;
- biosB0[0x4c] = psxBios_StopCARD;
- //biosB0[0x4d] = psxBios_sys_b0_4d;
- biosB0[0x4e] = psxBios__card_write;
- biosB0[0x4f] = psxBios__card_read;
- biosB0[0x50] = psxBios__new_card;
- biosB0[0x51] = psxBios_Krom2RawAdd;
- //biosB0[0x52] = psxBios_sys_b0_52;
- //biosB0[0x53] = psxBios_sys_b0_53;
- //biosB0[0x54] = psxBios__get_errno;
- //biosB0[0x55] = psxBios__get_error;
- biosB0[0x56] = psxBios_GetC0Table;
- biosB0[0x57] = psxBios_GetB0Table;
- biosB0[0x58] = psxBios__card_chan;
- //biosB0[0x59] = psxBios_sys_b0_59;
- //biosB0[0x5a] = psxBios_sys_b0_5a;
- biosB0[0x5b] = psxBios_ChangeClearPad;
- //biosB0[0x5c] = psxBios__card_status;
- //biosB0[0x5d] = psxBios__card_wait;
-//*******************C0 CALLS****************************
- //biosC0[0x00] = psxBios_InitRCnt;
- //biosC0[0x01] = psxBios_InitException;
- biosC0[0x02] = psxBios_SysEnqIntRP;
- biosC0[0x03] = psxBios_SysDeqIntRP;
- //biosC0[0x04] = psxBios_get_free_EvCB_slot;
- //biosC0[0x05] = psxBios_get_free_TCB_slot;
- //biosC0[0x06] = psxBios_ExceptionHandler;
- //biosC0[0x07] = psxBios_InstallExeptionHandler;
- //biosC0[0x08] = psxBios_SysInitMemory;
- //biosC0[0x09] = psxBios_SysInitKMem;
- biosC0[0x0a] = psxBios_ChangeClearRCnt;
- //biosC0[0x0b] = psxBios_SystemError;
- //biosC0[0x0c] = psxBios_InitDefInt;
- //biosC0[0x0d] = psxBios_sys_c0_0d;
- //biosC0[0x0e] = psxBios_sys_c0_0e;
- //biosC0[0x0f] = psxBios_sys_c0_0f;
- //biosC0[0x10] = psxBios_sys_c0_10;
- //biosC0[0x11] = psxBios_sys_c0_11;
- //biosC0[0x12] = psxBios_InstallDevices;
- //biosC0[0x13] = psxBios_FlushStfInOutPut;
- //biosC0[0x14] = psxBios_sys_c0_14;
- //biosC0[0x15] = psxBios__cdevinput;
- //biosC0[0x16] = psxBios__cdevscan;
- //biosC0[0x17] = psxBios__circgetc;
- //biosC0[0x18] = psxBios__circputc;
- //biosC0[0x19] = psxBios_ioabort;
- //biosC0[0x1a] = psxBios_sys_c0_1a
- //biosC0[0x1b] = psxBios_KernelRedirect;
- //biosC0[0x1c] = psxBios_PatchAOTable;
-//************** THE END ***************************************
-/**/
- base = 0x1000;
- size = sizeof(EvCB) * 32;
- Event = (void *)&psxR[base]; base += size * 6;
- memset(Event, 0, size * 6);
- HwEV = Event;
- EvEV = Event + 32;
- RcEV = Event + 32 * 2;
- UeEV = Event + 32 * 3;
- SwEV = Event + 32 * 4;
- ThEV = Event + 32 * 5;
-
- ptr = (u32 *)&psxM[0x0874]; // b0 table
- ptr[0] = SWAPu32(0x4c54 - 0x884);
-
- ptr = (u32 *)&psxM[0x0674]; // c0 table
- ptr[6] = SWAPu32(0xc80);
-
- memset(SysIntRP, 0, sizeof(SysIntRP));
- memset(Thread, 0, sizeof(Thread));
- Thread[0].status = 2; // main thread
-
- jmp_int = NULL;
- pad_buf = NULL;
- pad_buf1 = NULL;
- pad_buf2 = NULL;
- pad_buf1len = pad_buf2len = 0;
- heap_addr = NULL;
- heap_end = NULL;
- CardState = -1;
- CurThread = 0;
- memset(FDesc, 0, sizeof(FDesc));
- card_active_chan = 0;
-
- psxMu32ref(0x0150) = SWAPu32(0x160);
- psxMu32ref(0x0154) = SWAPu32(0x320);
- psxMu32ref(0x0160) = SWAPu32(0x248);
- strcpy((char *)&psxM[0x248], "bu");
-/* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
- psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
- psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
- psxMu32ref(0x09e0) = SWAPu32(0x43d0);
- psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
-*/
- // opcode HLE
- psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
- psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
- psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
- psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
- psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
- psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
- psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
- psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
- psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
- psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
-
- // initial stack pointer for BIOS interrupt
- psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
-
- // initial RNG seed
- psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
-
- // fonts
- len = 0x80000 - 0x66000;
- uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
- len = 0x80000 - 0x69d68;
- uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
-
- // memory size 2 MB
- psxHu32ref(0x1060) = SWAPu32(0x00000b88);
-
- hleSoftCall = FALSE;
-}
-
-void psxBiosShutdown() {
-}
-
-#define psxBios_PADpoll(pad) { \
- PAD##pad##_startPoll(pad); \
- pad_buf##pad[0] = 0; \
- pad_buf##pad[1] = PAD##pad##_poll(0x42); \
- if (!(pad_buf##pad[1] & 0x0f)) { \
- bufcount = 32; \
- } else { \
- bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
- } \
- PAD##pad##_poll(0); \
- i = 2; \
- while (bufcount--) { \
- pad_buf##pad[i++] = PAD##pad##_poll(0); \
- } \
-}
-
-void biosInterrupt() {
- int i, bufcount;
-
-// if (psxHu32(0x1070) & 0x1) { // Vsync
- if (pad_buf != NULL) {
- u32 *buf = (u32*)pad_buf;
-
- if (!Config.UseNet) {
- PAD1_startPoll(1);
- if (PAD1_poll(0x42) == 0x23) {
- PAD1_poll(0);
- *buf = PAD1_poll(0) << 8;
- *buf |= PAD1_poll(0);
- PAD1_poll(0);
- *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
- *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
- } else {
- PAD1_poll(0);
- *buf = PAD1_poll(0) << 8;
- *buf|= PAD1_poll(0);
- }
-
- PAD2_startPoll(2);
- if (PAD2_poll(0x42) == 0x23) {
- PAD2_poll(0);
- *buf |= PAD2_poll(0) << 24;
- *buf |= PAD2_poll(0) << 16;
- PAD2_poll(0);
- *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
- *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
- } else {
- PAD2_poll(0);
- *buf |= PAD2_poll(0) << 24;
- *buf |= PAD2_poll(0) << 16;
- }
- } else {
- u16 data;
-
- PAD1_startPoll(1);
- PAD1_poll(0x42);
- PAD1_poll(0);
- data = PAD1_poll(0) << 8;
- data |= PAD1_poll(0);
-
- if (NET_sendPadData(&data, 2) == -1)
- netError();
-
- if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
- netError();
- if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
- netError();
- }
- }
- if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
- psxBios_PADpoll(1);
-
- if (NET_sendPadData(pad_buf1, i) == -1)
- netError();
-
- if (NET_recvPadData(pad_buf1, 1) == -1)
- netError();
- if (NET_recvPadData(pad_buf2, 2) == -1)
- netError();
- } else {
- if (pad_buf1) {
- psxBios_PADpoll(1);
- }
-
- if (pad_buf2) {
- psxBios_PADpoll(2);
- }
- }
-
- if (psxHu32(0x1070) & 0x1) { // Vsync
- if (RcEV[3][1].status == EvStACTIVE) {
- softCall(RcEV[3][1].fhandler);
-// hwWrite32(0x1f801070, ~(1));
- }
- }
-
- if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
- int i;
-
- for (i = 0; i < 3; i++) {
- if (psxHu32(0x1070) & (1 << (i + 4))) {
- if (RcEV[i][1].status == EvStACTIVE) {
- softCall(RcEV[i][1].fhandler);
- }
- psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
- }
- }
- }
-}
-
-void psxBiosException() {
- int i;
-
- switch (psxRegs.CP0.n.Cause & 0x3c) {
- case 0x00: // Interrupt
-#ifdef PSXCPU_LOG
-// PSXCPU_LOG("interrupt\n");
-#endif
- SaveRegs();
-
- sp = psxMu32(0x6c80); // create new stack for interrupt handlers
-
- biosInterrupt();
-
- for (i = 0; i < 8; i++) {
- if (SysIntRP[i]) {
- u32 *queue = (u32 *)PSXM(SysIntRP[i]);
-
- s0 = queue[2];
- softCall(queue[1]);
- }
- }
-
- if (jmp_int != NULL) {
- int i;
-
- psxHwWrite32(0x1f801070, 0xffffffff);
-
- ra = jmp_int[0];
- sp = jmp_int[1];
- fp = jmp_int[2];
- for (i = 0; i < 8; i++) // s0-s7
- psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
- gp = jmp_int[11];
-
- v0 = 1;
- pc0 = ra;
- return;
- }
- psxHwWrite16(0x1f801070, 0);
- break;
-
- case 0x20: // Syscall
-#ifdef PSXCPU_LOG
- PSXCPU_LOG("syscall exp %x\n", a0);
-#endif
- switch (a0) {
- case 1: // EnterCritical - disable irq's
- psxRegs.CP0.n.Status &= ~0x404;
-v0=1; // HDHOSHY experimental patch: Spongebob, Coldblood, fearEffect, Medievil2, Martian Gothic
- break;
-
- case 2: // ExitCritical - enable irq's
- psxRegs.CP0.n.Status |= 0x404;
- break;
- }
- pc0 = psxRegs.CP0.n.EPC + 4;
-
- psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
- ((psxRegs.CP0.n.Status & 0x3c) >> 2);
- return;
-
- default:
-#ifdef PSXCPU_LOG
- PSXCPU_LOG("unknown bios exception!\n");
-#endif
- break;
- }
-
- pc0 = psxRegs.CP0.n.EPC;
- if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
-
- psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
- ((psxRegs.CP0.n.Status & 0x3c) >> 2);
-}
-
-#define bfreeze(ptr, size) { \
- if (Mode == 1) memcpy(&psxR[base], ptr, size); \
- if (Mode == 0) memcpy(ptr, &psxR[base], size); \
- base += size; \
-}
-
-#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
-#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
-
-#define bfreezepsxMptr(ptr, type) { \
- if (Mode == 1) { \
- if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
- else psxRu32ref(base) = 0; \
- } else { \
- if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
- else (ptr) = NULL; \
- } \
- base += sizeof(u32); \
-}
-
-void psxBiosFreeze(int Mode) {
- u32 base = 0x40000;
-
- bfreezepsxMptr(jmp_int, u32);
- bfreezepsxMptr(pad_buf, int);
- bfreezepsxMptr(pad_buf1, char);
- bfreezepsxMptr(pad_buf2, char);
- bfreezepsxMptr(heap_addr, u32);
- bfreezel(&pad_buf1len);
- bfreezel(&pad_buf2len);
- bfreezes(regs);
- bfreezes(SysIntRP);
- bfreezel(&CardState);
- bfreezes(Thread);
- bfreezel(&CurThread);
- bfreezes(FDesc);
- bfreezel(&card_active_chan);
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* + * Internal simulated HLE BIOS. + */ + +#include "psxbios.h" +#include "psxhw.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 t8 (psxRegs.GPR.n.t8) +#define t9 (psxRegs.GPR.n.t9) +#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 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)) + +typedef struct { + u32 desc; + s32 status; + s32 mode; + u32 fhandler; +} EvCB[32]; + +#define EvStUNUSED 0x0000 +#define EvStWAIT 0x1000 +#define EvStACTIVE 0x2000 +#define EvStALREADY 0x4000 + +#define EvMdINTR 0x1000 +#define EvMdNOINTR 0x2000 + +/* +typedef struct { + s32 next; + s32 func1; + s32 func2; + s32 pad; +} SysRPst; +*/ + +typedef struct { + s32 status; + s32 mode; + u32 reg[32]; + u32 func; +} TCB; + +typedef struct { + u32 _pc0; + u32 gp0; + u32 t_addr; + u32 t_size; + u32 d_addr; + u32 d_size; + u32 b_addr; + u32 b_size; + u32 S_addr; + u32 s_size; + u32 _sp, _fp, _gp, ret, base; +} EXEC; + +struct DIRENTRY { + char name[20]; + s32 attr; + s32 size; + u32 next; + s32 head; + char system[4]; +}; + +typedef struct { + char name[32]; + u32 mode; + u32 offset; + u32 size; + u32 mcfile; +} FileDesc; + +static u32 *jmp_int = NULL; +static int *pad_buf = NULL; +static char *pad_buf1 = NULL, *pad_buf2 = NULL; +static int pad_buf1len, pad_buf2len; + +static u32 regs[35]; +static EvCB *Event; +static EvCB *HwEV; // 0xf0 +static EvCB *EvEV; // 0xf1 +static EvCB *RcEV; // 0xf2 +static EvCB *UeEV; // 0xf3 +static EvCB *SwEV; // 0xf4 +static EvCB *ThEV; // 0xff +static u32 *heap_addr = NULL; +static u32 *heap_end = NULL; +static u32 SysIntRP[8]; +static int CardState = -1; +static TCB Thread[8]; +static int CurThread = 0; +static FileDesc FDesc[32]; +static u32 card_active_chan = 0; + +boolean hleSoftCall = FALSE; + +static inline void softCall(u32 pc) { + pc0 = pc; + ra = 0x80001000; + + hleSoftCall = TRUE; + + while (pc0 != 0x80001000) psxCpu->ExecuteBlock(); + + hleSoftCall = FALSE; +} + +static inline void softCall2(u32 pc) { + u32 sra = ra; + pc0 = pc; + ra = 0x80001000; + + hleSoftCall = TRUE; + + while (pc0 != 0x80001000) psxCpu->ExecuteBlock(); + ra = sra; + + hleSoftCall = FALSE; +} + +static inline void DeliverEvent(u32 ev, u32 spec) { + if (Event[ev][spec].status != EvStACTIVE) return; + +// Event[ev][spec].status = EvStALREADY; + if (Event[ev][spec].mode == EvMdINTR) { + softCall2(Event[ev][spec].fhandler); + } else Event[ev][spec].status = EvStALREADY; +} + +static inline void SaveRegs() { + memcpy(regs, psxRegs.GPR.r, 32*4); + regs[32] = psxRegs.GPR.n.lo; + regs[33] = psxRegs.GPR.n.hi; + regs[34] = psxRegs.pc; +} + +static inline void LoadRegs() { + memcpy(psxRegs.GPR.r, regs, 32*4); + psxRegs.GPR.n.lo = regs[32]; + psxRegs.GPR.n.hi = regs[33]; +} + +/* * +// * +// * +// System calls A0 */ + + +void psxBios_abs() { // 0x0e + if ((s32)a0 < 0) v0 = -(s32)a0; + else v0 = a0; + pc0 = ra; +} + +void psxBios_labs() { // 0x0f + psxBios_abs(); +} + +void psxBios_atoi() { // 0x10 + s32 n = 0, f = 0; + char *p = (char *)Ra0; + + for (;;p++) { + switch (*p) { + case ' ': case '\t': continue; + case '-': f++; + case '+': p++; + } + break; + } + + while (*p >= '0' && *p <= '9') { + n = n * 10 + *p++ - '0'; + } + + v0 = (f ? -n : n); + pc0 = ra; +} + +void psxBios_atol() { // 0x11 + psxBios_atoi(); +} + +void psxBios_setjmp() { // 0x13 + u32 *jmp_buf = (u32 *)Ra0; + int i; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]); +#endif + + jmp_buf[0] = ra; + jmp_buf[1] = sp; + jmp_buf[2] = fp; + for (i = 0; i < 8; i++) // s0-s7 + jmp_buf[3 + i] = psxRegs.GPR.r[16 + i]; + jmp_buf[11] = gp; + + v0 = 0; pc0 = ra; +} + +void psxBios_longjmp() { // 0x14 + u32 *jmp_buf = (u32 *)Ra0; + int i; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]); +#endif + + ra = jmp_buf[0]; /* ra */ + sp = jmp_buf[1]; /* sp */ + fp = jmp_buf[2]; /* fp */ + for (i = 0; i < 8; i++) // s0-s7 + psxRegs.GPR.r[16 + i] = jmp_buf[3 + i]; + gp = jmp_buf[11]; /* gp */ + + v0 = a1; pc0 = ra; +} + +void psxBios_strcat() { // 0x15 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1); +#endif + + while (*p1++); + --p1; + while ((*p1++ = *p2++) != '\0'); + + v0 = a0; pc0 = ra; +} + +void psxBios_strncat() { // 0x16 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + s32 n = a2; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2); +#endif + + while (*p1++); + --p1; + while ((*p1++ = *p2++) != '\0') { + if (--n < 0) { + *--p1 = '\0'; + break; + } + } + + v0 = a0; pc0 = ra; +} + +void psxBios_strcmp() { // 0x17 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1); +#endif + + while (*p1 == *p2++) { + if (*p1++ == '\0') { + v0 = 0; + pc0 = ra; + return; + } + } + + v0 = (*p1 - *--p2); + pc0 = ra; +} + +void psxBios_strncmp() { // 0x18 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + s32 n = a2; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2); +#endif + + while (--n >= 0 && *p1 == *p2++) { + if (*p1++ == '\0') { + v0 = 0; + pc0 = ra; + return; + } + } + + v0 = (n < 0 ? 0 : *p1 - *--p2); + pc0 = ra; +} + +void psxBios_strcpy() { // 0x19 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + while ((*p1++ = *p2++) != '\0'); + + v0 = a0; pc0 = ra; +} + +void psxBios_strncpy() { // 0x1a + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + s32 n = a2, i; + + for (i = 0; i < n; i++) { + if ((*p1++ = *p2++) == '\0') { + while (++i < n) { + *p1++ = '\0'; + } + v0 = a0; pc0 = ra; + return; + } + } + + v0 = a0; pc0 = ra; +} + +void psxBios_strlen() { // 0x1b + char *p = (char *)Ra0; + v0 = 0; + while (*p++) v0++; + pc0 = ra; +} + +void psxBios_index() { // 0x1c + char *p = (char *)Ra0; + + do { + if (*p == a1) { + v0 = a0 + (p - (char *)Ra0); + pc0 = ra; + return; + } + } while (*p++ != '\0'); + + v0 = 0; pc0 = ra; +} + +void psxBios_rindex() { // 0x1d + char *p = (char *)Ra0; + + v0 = 0; + + do { + if (*p == a1) + v0 = a0 + (p - (char *)Ra0); + } while (*p++ != '\0'); + + pc0 = ra; +} + +void psxBios_strchr() { // 0x1e + psxBios_index(); +} + +void psxBios_strrchr() { // 0x1f + psxBios_rindex(); +} + +void psxBios_strpbrk() { // 0x20 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc; + + while ((c = *p1++) != '\0') { + for (scanp = p2; (sc = *scanp++) != '\0';) { + if (sc == c) { + v0 = a0 + (p1 - 1 - (char *)Ra0); + pc0 = ra; + return; + } + } + } + + // BUG: return a0 instead of NULL if not found + v0 = a0; pc0 = ra; +} + +void psxBios_strspn() { // 0x21 + char *p1, *p2; + + for (p1 = (char *)Ra0; *p1 != '\0'; p1++) { + for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++); + if (*p2 == '\0') break; + } + + v0 = p1 - (char *)Ra0; pc0 = ra; +} + +void psxBios_strcspn() { // 0x22 + char *p1, *p2; + + for (p1 = (char *)Ra0; *p1 != '\0'; p1++) { + for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++); + if (*p2 != '\0') break; + } + + v0 = p1 - (char *)Ra0; pc0 = ra; +} + +void psxBios_strtok() { // 0x23 + char *pcA0 = (char *)Ra0; + char *pcRet = strtok(pcA0, (char *)Ra1); + if (pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +void psxBios_strstr() { // 0x24 + char *p = (char *)Ra0, *p1, *p2; + + while (*p != '\0') { + p1 = p; + p2 = (char *)Ra1; + + while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) { + p1++; p2++; + } + + if (*p2 == '\0') { + v0 = a0 + (p - (char *)Ra0); + pc0 = ra; + return; + } + + p++; + } + + v0 = 0; pc0 = ra; +} + +void psxBios_toupper() { // 0x25 + v0 = (s8)(a0 & 0xff); + if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A'; + pc0 = ra; +} + +void psxBios_tolower() { // 0x26 + v0 = (s8)(a0 & 0xff); + if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A'; + pc0 = ra; +} + +void psxBios_bcopy() { // 0x27 + char *p1 = (char *)Ra1, *p2 = (char *)Ra0; + while (a2-- > 0) *p1++ = *p2++; + + pc0 = ra; +} + +void psxBios_bzero() { // 0x28 + char *p = (char *)Ra0; + while (a1-- > 0) *p++ = '\0'; + + pc0 = ra; +} + +void psxBios_bcmp() { // 0x29 + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + + if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; } + + while (a2-- > 0) { + if (*p1++ != *p2++) { + v0 = *p1 - *p2; // BUG: compare the NEXT byte + pc0 = ra; + return; + } + } + + v0 = 0; pc0 = ra; +} + +void psxBios_memcpy() { // 0x2a + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + while (a2-- > 0) *p1++ = *p2++; + + v0 = a0; pc0 = ra; +} + +void psxBios_memset() { // 0x2b + char *p = (char *)Ra0; + while (a2-- > 0) *p++ = (char)a1; + + v0 = a0; pc0 = ra; +} + +void psxBios_memmove() { // 0x2c + char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + + if (p2 <= p1 && p2 + a2 > p1) { + a2++; // BUG: copy one more byte here + p1 += a2; + p2 += a2; + while (a2-- > 0) *--p1 = *--p2; + } else { + while (a2-- > 0) *p1++ = *p2++; + } + + v0 = a0; pc0 = ra; +} + +void psxBios_memcmp() { // 0x2d + psxBios_bcmp(); +} + +void psxBios_memchr() { // 0x2e + char *p = (char *)Ra0; + + while (a2-- > 0) { + if (*p++ != (s8)a1) continue; + v0 = a0 + (p - (char *)Ra0 - 1); + pc0 = ra; + return; + } + + v0 = 0; pc0 = ra; +} + +void psxBios_rand() { // 0x2f + u32 s = psxMu32(0x9010) * 1103515245 + 12345; + v0 = (s >> 16) & 0x7fff; + psxMu32ref(0x9010) = SWAPu32(s); + pc0 = ra; +} + +void psxBios_srand() { // 0x30 + psxMu32ref(0x9010) = SWAPu32(a0); + pc0 = ra; +} + +static u32 qscmpfunc, qswidth; + +static inline int qscmp(char *a, char *b) { + u32 sa0 = a0; + + a0 = sa0 + (a - (char *)PSXM(sa0)); + a1 = sa0 + (b - (char *)PSXM(sa0)); + + softCall2(qscmpfunc); + + a0 = sa0; + return (s32)v0; +} + +static inline void qexchange(char *i, char *j) { + char t; + int n = qswidth; + + do { + t = *i; + *i++ = *j; + *j++ = t; + } while (--n); +} + +static inline void q3exchange(char *i, char *j, char *k) { + char t; + int n = qswidth; + + do { + t = *i; + *i++ = *k; + *k++ = *j; + *j++ = t; + } while (--n); +} + +static void qsort_main(char *a, char *l) { + char *i, *j, *lp, *hp; + int c; + unsigned int n; + +start: + if ((n = l - a) <= qswidth) + return; + n = qswidth * (n / (2 * qswidth)); + hp = lp = a + n; + i = a; + j = l - qswidth; + while (TRUE) { + if (i < lp) { + if ((c = qscmp(i, lp)) == 0) { + qexchange(i, lp -= qswidth); + continue; + } + if (c < 0) { + i += qswidth; + continue; + } + } + +loop: + if (j > hp) { + if ((c = qscmp(hp, j)) == 0) { + qexchange(hp += qswidth, j); + goto loop; + } + if (c > 0) { + if (i == lp) { + q3exchange(i, hp += qswidth, j); + i = lp += qswidth; + goto loop; + } + qexchange(i, j); + j -= qswidth; + i += qswidth; + continue; + } + j -= qswidth; + goto loop; + } + + if (i == lp) { + if (lp - a >= l - hp) { + qsort_main(hp + qswidth, l); + l = lp; + } else { + qsort_main(a, lp); + a = hp + qswidth; + } + goto start; + } + + q3exchange(j, lp -= qswidth, i); + j = hp -= qswidth; + } +} + +void psxBios_qsort() { // 0x31 + qswidth = a2; + qscmpfunc = a3; + qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2); + + pc0 = ra; +} + +void psxBios_malloc() { // 0x33 + unsigned int *chunk, *newchunk; + unsigned int dsize, csize, cstat; + int colflag; +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]); +#endif + + // scan through heap and combine free chunks of space + chunk = heap_addr; + colflag = 0; + while(chunk < heap_end) { + // get size and status of actual chunk + csize = ((u32)*chunk) & 0xfffffffc; + cstat = ((u32)*chunk) & 1; + + // it's a free chunk + if(cstat == 1) { + if(colflag == 0) { + newchunk = chunk; + dsize = csize; + colflag = 1; // let's begin a new collection of free memory + } + else dsize += (csize+4); // add the new size including header + } + // not a free chunk: did we start a collection ? + else { + if(colflag == 1) { // collection is over + colflag = 0; + *newchunk = SWAP32(dsize | 1); + } + } + + // next chunk + chunk = (u32*)((uptr)chunk + csize + 4); + } + // if neccessary free memory on end of heap + if (colflag == 1) + *newchunk = SWAP32(dsize | 1); + + chunk = heap_addr; + csize = ((u32)*chunk) & 0xfffffffc; + cstat = ((u32)*chunk) & 1; + dsize = (a0 + 3) & 0xfffffffc; + + // exit on uninitialized heap + if (chunk == NULL) { + SysPrintf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); + v0 = 0; + pc0 = ra; + return; + } + + // search an unused chunk that is big enough until the end of the heap + while ((dsize > csize || cstat == 0) && chunk < heap_end ) { + chunk = (u32*)((uptr)chunk + csize + 4); + csize = ((u32)*chunk) & 0xfffffffc; + cstat = ((u32)*chunk) & 1; + } + + // catch out of memory + if(chunk >= heap_end) { SysPrintf("malloc %x,%x: Out of memory error!\n", v0, a0); v0 = 0; pc0 = ra; return; } + + // allocate memory + if(dsize == csize) { + // chunk has same size + *chunk &= 0xfffffffc; + } + else { + // split free chunk + *chunk = SWAP32(dsize); + newchunk = (u32*)((uptr)chunk + dsize + 4); + *newchunk = SWAP32((csize - dsize - 4) & 0xfffffffc | 1); + } + + // return pointer to allocated memory + v0 = ((unsigned long)chunk - (unsigned long)psxM) + 4; + v0|= 0x80000000; + SysPrintf ("malloc %x,%x\n", v0, a0); + pc0 = ra; +} + +void psxBios_free() { // 0x34 + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]); +#endif + + SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4)); + + *(u32*)(Ra0-4) |= 1; // set chunk to free + pc0 = ra; +} + +void psxBios_calloc() { // 0x37 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]); +#endif + + a0 = a0 * a1; + psxBios_malloc(); + memset(Rv0, 0, a0); +} + +void psxBios_realloc() { // 0x38 + u32 block = a0; + u32 size = a1; +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]); +#endif + + a0 = block; + psxBios_free(); + a0 = size; + psxBios_malloc(); +} + + +/* InitHeap(void *block , int n) */ +void psxBios_InitHeap() { // 0x39 + unsigned int size; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]); +#endif + + if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff); + else size = a1; + + size &= 0xfffffffc; + + heap_addr = (u32 *)Ra0; + heap_end = (u32 *)((u8 *)heap_addr + size); + *heap_addr = SWAP32(size | 1); + + SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (uptr)heap_addr-(uptr)psxM, size); + + pc0 = ra; +} + +void psxBios_getchar() { //0x3b + v0 = getchar(); pc0 = ra; +} + +void psxBios_printf() { // 0x3f + char tmp[1024]; + char tmp2[1024]; + u32 save[4]; + char *ptmp = tmp; + int n=1, i=0, j; + + memcpy(save, (char*)PSXM(sp), 4 * 4); + psxMu32ref(sp) = SWAP32((u32)a0); + psxMu32ref(sp + 4) = SWAP32((u32)a1); + psxMu32ref(sp + 8) = SWAP32((u32)a2); + psxMu32ref(sp + 12) = SWAP32((u32)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(tmp); + + pc0 = ra; +} + +/* + * long Load(char *name, struct EXEC *header); + */ + +void psxBios_Load() { // 0x42 + EXE_HEADER eheader; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1); +#endif + + if (LoadCdromFile(Ra0, &eheader) == 0) { + memcpy(Ra1, ((char*)&eheader)+16, sizeof(EXEC)); + v0 = 1; + } else v0 = 0; + + pc0 = ra; +} + +/* + * int Exec(struct EXEC *header , int argc , char **argv); + */ + +void psxBios_Exec() { // 43 + EXEC *header = (EXEC*)Ra0; + u32 tmp; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2); +#endif + + header->_sp = sp; + header->_fp = fp; + header->_sp = sp; + header->_gp = gp; + header->ret = ra; + header->base = s0; + + if (header->S_addr != 0) { + tmp = header->S_addr + header->s_size; + sp = tmp; + fp = sp; + } + + gp = header->gp0; + + s0 = a0; + + a0 = a1; + a1 = a2; + + ra = 0x8000; + pc0 = header->_pc0; +} + +void psxBios_FlushCache() { // 44 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]); +#endif + + psxRegs.ICache_valid = 0; + + pc0 = ra; +} + +void psxBios_GPU_dw() { // 0x46 + int size; + s32 *ptr; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]); +#endif + + GPU_writeData(0xa0000000); + GPU_writeData((a1<<16)|(a0&0xffff)); + GPU_writeData((a3<<16)|(a2&0xffff)); + size = (a2*a3+1)/2; + ptr = (s32*)PSXM(Rsp[4]); //that is correct? + do { + GPU_writeData(SWAP32(*ptr)); + ptr++; + } while(--size); + + pc0 = ra; +} + +void psxBios_mem2vram() { // 0x47 + int size; + + GPU_writeData(0xa0000000); + GPU_writeData((a1<<16)|(a0&0xffff)); + GPU_writeData((a3<<16)|(a2&0xffff)); + size = (a2*a3+1)/2; + GPU_writeStatus(0x04000002); + psxHwWrite32(0x1f8010f4,0); + psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800); + psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy... + psxHwWrite32(0x1f8010a4,((size/16)<<16)|16); + psxHwWrite32(0x1f8010a8,0x01000201); + + pc0 = ra; +} + +void psxBios_SendGPU() { // 0x48 + GPU_writeStatus(a0); + pc0 = ra; +} + +void psxBios_GPU_cw() { // 0x49 + GPU_writeData(a0); + pc0 = ra; +} + +void psxBios_GPU_cwb() { // 0x4a + s32 *ptr = (s32*)Ra0; + int size = a1; + while(size--) { + GPU_writeData(SWAP32(*ptr)); + ptr++; + } + + pc0 = ra; +} + +void psxBios_GPU_SendPackets() { //4b: + GPU_writeStatus(0x04000002); + psxHwWrite32(0x1f8010f4,0); + psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800); + psxHwWrite32(0x1f8010a0,a0); + psxHwWrite32(0x1f8010a4,0); + psxHwWrite32(0x1f8010a8,0x010000401); + pc0 = ra; +} + +void psxBios_sys_a0_4c() { // 0x4c GPU relate + psxHwWrite32(0x1f8010a8,0x00000401); + GPU_writeData(0x0400000); + GPU_writeData(0x0200000); + GPU_writeData(0x0100000); + + pc0 = ra; +} + +void psxBios_GPU_GetGPUStatus() { // 0x4d + v0 = GPU_readStatus(); + pc0 = ra; +} + +#undef s_addr + +void psxBios_LoadExec() { // 51 + EXEC *header = (EXEC*)PSXM(0xf000); + u32 s_addr, s_size; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2); +#endif + s_addr = a1; s_size = a2; + + a1 = 0xf000; + psxBios_Load(); + + header->S_addr = s_addr; + header->s_size = s_size; + + a0 = 0xf000; a1 = 0; a2 = 0; + psxBios_Exec(); +} + +void psxBios__bu_init() { // 70 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]); +#endif + + DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 + DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + + pc0 = ra; +} + +void psxBios__96_init() { // 71 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]); +#endif + + pc0 = ra; +} + +void psxBios__96_remove() { // 72 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]); +#endif + + pc0 = ra; +} + +void psxBios_SetMem() { // 9f + u32 new = psxHu32(0x1060); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1); +#endif + + switch(a0) { + case 2: + psxHu32ref(0x1060) = SWAP32(new); + psxMu32ref(0x060) = a0; + SysPrintf("Change effective memory : %d MBytes\n",a0); + break; + + case 8: + psxHu32ref(0x1060) = SWAP32(new | 0x300); + psxMu32ref(0x060) = a0; + SysPrintf("Change effective memory : %d MBytes\n",a0); + + default: + SysPrintf("Effective memory must be 2/8 MBytes\n"); + break; + } + + pc0 = ra; +} + +void psxBios__card_info() { // ab +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0); +#endif + + card_active_chan = a0; + +// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 + DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + + v0 = 1; pc0 = ra; +} + +void psxBios__card_load() { // ac +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0); +#endif + + card_active_chan = a0; + +// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 + DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + + v0 = 1; pc0 = ra; +} + +/* System calls B0 */ + +void psxBios_SetRCnt() { // 02 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]); +#endif + + a0&= 0x3; + if (a0 != 3) { + u32 mode=0; + + psxRcntWtarget(a0, a1); + if (a2&0x1000) mode|= 0x050; // Interrupt Mode + if (a2&0x0100) mode|= 0x008; // Count to 0xffff + if (a2&0x0010) mode|= 0x001; // Timer stop mode + if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode + else { if (a2&0x0001) mode|= 0x100; } // System Clock mode + + psxRcntWmode(a0, mode); + } + pc0 = ra; +} + +void psxBios_GetRCnt() { // 03 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]); +#endif + + a0&= 0x3; + if (a0 != 3) v0 = psxRcntRcount(a0); + else v0 = 0; + pc0 = ra; +} + +void psxBios_StartRCnt() { // 04 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]); +#endif + + a0&= 0x3; + if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4)))); + else psxHu32ref(0x1074)|= SWAPu32(0x1); + v0 = 1; pc0 = ra; +} + +void psxBios_StopRCnt() { // 05 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]); +#endif + + a0&= 0x3; + if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4)))); + else psxHu32ref(0x1074)&= SWAPu32(~0x1); + pc0 = ra; +} + +void psxBios_ResetRCnt() { // 06 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]); +#endif + + a0&= 0x3; + if (a0 != 3) { + psxRcntWmode(a0, 0); + psxRcntWtarget(a0, 0); + psxRcntWcount(a0, 0); + } + pc0 = ra; +} + + +/* gets ev for use with Event */ +#define GetEv() \ + ev = (a0 >> 24) & 0xf; \ + if (ev == 0xf) ev = 0x5; \ + ev*= 32; \ + ev+= a0&0x1f; + +/* gets spec for use with Event */ +#define GetSpec() \ + spec = 0; \ + switch (a1) { \ + case 0x0301: spec = 16; break; \ + case 0x0302: spec = 17; break; \ + default: \ + for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \ + break; \ + } + +void psxBios_DeliverEvent() { // 07 + int ev, spec; + int i; + + GetEv(); + GetSpec(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec); +#endif + + DeliverEvent(ev, spec); + + pc0 = ra; +} + +void psxBios_OpenEvent() { // 08 + int ev, spec; + int i; + + GetEv(); + GetSpec(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3); +#endif + + Event[ev][spec].status = EvStWAIT; + Event[ev][spec].mode = a2; + Event[ev][spec].fhandler = a3; + + v0 = ev | (spec << 8); + pc0 = ra; +} + +void psxBios_CloseEvent() { // 09 + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec); +#endif + + Event[ev][spec].status = EvStUNUSED; + + v0 = 1; pc0 = ra; +} + +void psxBios_WaitEvent() { // 0a + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec); +#endif + + Event[ev][spec].status = EvStACTIVE; + + v0 = 1; pc0 = ra; +} + +void psxBios_TestEvent() { // 0b + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + + if (Event[ev][spec].status == EvStALREADY) { + Event[ev][spec].status = EvStACTIVE; v0 = 1; + } else v0 = 0; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0); +#endif + + pc0 = ra; +} + +void psxBios_EnableEvent() { // 0c + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec); +#endif + + Event[ev][spec].status = EvStACTIVE; + + v0 = 1; pc0 = ra; +} + +void psxBios_DisableEvent() { // 0d + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec); +#endif + + Event[ev][spec].status = EvStWAIT; + + v0 = 1; pc0 = ra; +} + +/* + * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp); + */ + +void psxBios_OpenTh() { // 0e + int th; + + for (th=1; th<8; th++) + if (Thread[th].status == 0) break; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th); +#endif + + Thread[th].status = 1; + Thread[th].func = a0; + Thread[th].reg[29] = a1; + Thread[th].reg[28] = a2; + + v0 = th; pc0 = ra; +} + +/* + * int CloseTh(long thread); + */ + +void psxBios_CloseTh() { // 0f + int th = a0 & 0xff; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th); +#endif + + if (Thread[th].status == 0) { + v0 = 0; + } else { + Thread[th].status = 0; + v0 = 1; + } + + pc0 = ra; +} + +/* + * int ChangeTh(long thread); + */ + +void psxBios_ChangeTh() { // 10 + int th = a0 & 0xff; + +#ifdef PSXBIOS_LOG +// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th); +#endif + + if (Thread[th].status == 0 || CurThread == th) { + v0 = 0; + + pc0 = ra; + } else { + v0 = 1; + + if (Thread[CurThread].status == 2) { + Thread[CurThread].status = 1; + Thread[CurThread].func = ra; + memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4); + } + + memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4); + pc0 = Thread[th].func; + Thread[th].status = 2; + CurThread = th; + } +} + +void psxBios_InitPAD() { // 0x12 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]); +#endif + + pad_buf1 = (char*)Ra0; + pad_buf1len = a1; + pad_buf2 = (char*)Ra2; + pad_buf2len = a3; + + v0 = 1; pc0 = ra; +} + +void psxBios_StartPAD() { // 13 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]); +#endif + + psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1)); + psxRegs.CP0.n.Status |= 0x401; + pc0 = ra; +} + +void psxBios_StopPAD() { // 14 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); +#endif + + pad_buf1 = NULL; + pad_buf2 = NULL; + pc0 = ra; +} + +void psxBios_PAD_init() { // 15 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]); +#endif + psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1)); + pad_buf = (int *)Ra1; + *pad_buf = -1; + psxRegs.CP0.n.Status |= 0x401; + pc0 = ra; +} + +void psxBios_PAD_dr() { // 16 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]); +#endif + + v0 = -1; pc0 = ra; +} + +void psxBios_ReturnFromException() { // 17 + LoadRegs(); + + pc0 = psxRegs.CP0.n.EPC; + if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4; + + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +} + +void psxBios_ResetEntryInt() { // 18 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]); +#endif + + jmp_int = NULL; + pc0 = ra; +} + +void psxBios_HookEntryInt() { // 19 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]); +#endif + + jmp_int = (u32*)Ra0; + pc0 = ra; +} + +void psxBios_UnDeliverEvent() { // 0x20 + int ev, spec; + int i; + + GetEv(); + GetSpec(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec); +#endif + + if (Event[ev][spec].status == EvStALREADY && + Event[ev][spec].mode == EvMdNOINTR) + Event[ev][spec].status = EvStACTIVE; + + pc0 = ra; +} + +#define buopen(mcd) { \ + strcpy(FDesc[1 + mcd].name, Ra0+5); \ + FDesc[1 + mcd].offset = 0; \ + FDesc[1 + mcd].mode = a1; \ + \ + for (i=1; i<16; i++) { \ + ptr = Mcd##mcd##Data + 128 * i; \ + if ((*ptr & 0xF0) != 0x50) continue; \ + if (strcmp(FDesc[1 + mcd].name, ptr+0xa)) continue; \ + FDesc[1 + mcd].mcfile = i; \ + SysPrintf("open %s\n", ptr+0xa); \ + v0 = 1 + mcd; \ + break; \ + } \ + if (a1 & 0x200 && v0 == -1) { /* FCREAT */ \ + for (i=1; i<16; i++) { \ + int j, xor = 0; \ + \ + ptr = Mcd##mcd##Data + 128 * i; \ + if ((*ptr & 0xF0) == 0x50) continue; \ + ptr[0] = 0x50 | (u8)(a1 >> 16); \ + ptr[4] = 0x00; \ + ptr[5] = 0x20; \ + ptr[6] = 0x00; \ + ptr[7] = 0x00; \ + ptr[8] = 'B'; \ + ptr[9] = 'I'; \ + strcpy(ptr+0xa, FDesc[1 + mcd].name); \ + for (j=0; j<127; j++) xor^= ptr[j]; \ + ptr[127] = xor; \ + FDesc[1 + mcd].mcfile = i; \ + SysPrintf("openC %s\n", ptr); \ + v0 = 1 + mcd; \ + SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 128); \ + break; \ + } \ + } \ +} + +/* + * int open(char *name , int mode); + */ + +void psxBios_open() { // 0x32 + int i; + char *ptr; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1); +#endif + + v0 = -1; + + if (!strncmp(Ra0, "bu00", 4)) { + buopen(1); + } + + if (!strncmp(Ra0, "bu10", 4)) { + buopen(2); + } + + pc0 = ra; +} + +/* + * int lseek(int fd , int offset , int whence); + */ + +void psxBios_lseek() { // 0x33 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2); +#endif + + switch (a2) { + case 0: // SEEK_SET + FDesc[a0].offset = a1; + v0 = a1; +// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 +// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + break; + + case 1: // SEEK_CUR + FDesc[a0].offset+= a1; + v0 = FDesc[a0].offset; + break; + } + + pc0 = ra; +} + +#define buread(mcd) { \ + SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \ + ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ + memcpy(Ra1, ptr, a2); \ + if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ + else v0 = a2; \ + FDesc[1 + mcd].offset += v0; \ + DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ + DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ +} + +/* + * int read(int fd , void *buf , int nbytes); + */ + +void psxBios_read() { // 0x34 + char *ptr; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2); +#endif + + v0 = -1; + + switch (a0) { + case 2: buread(1); break; + case 3: buread(2); break; + } + + pc0 = ra; +} + +#define buwrite(mcd) { \ + u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ + SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \ + ptr = Mcd##mcd##Data + offset; \ + memcpy(ptr, Ra1, a2); \ + FDesc[1 + mcd].offset += a2; \ + SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, a2); \ + if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ + else v0 = a2; \ + DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ + DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ +} + +/* + * int write(int fd , void *buf , int nbytes); + */ + +void psxBios_write() { // 0x35/0x03 + char *ptr; + + if (a0 == 1) { // stdout + char *ptr = Ra1; + + while (a2 > 0) { + SysPrintf("%c", *ptr++); a2--; + } + pc0 = ra; return; + } +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2); +#endif + + v0 = -1; + + switch (a0) { + case 2: buwrite(1); break; + case 3: buwrite(2); break; + } + + pc0 = ra; +} + +/* + * int close(int fd); + */ + +void psxBios_close() { // 0x36 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0); +#endif + + v0 = a0; + pc0 = ra; +} + +void psxBios_putchar() { // 3d + SysPrintf("%c", (char)a0); + pc0 = ra; +} + +void psxBios_puts() { // 3e/3f + SysPrintf(Ra0); + pc0 = ra; +} + +char ffile[64], *pfile; +int nfile; + +#define bufile(mcd) { \ + while (nfile < 16) { \ + int match=1; \ + \ + ptr = Mcd##mcd##Data + 128 * nfile; \ + nfile++; \ + if ((*ptr & 0xF0) != 0x50) continue; \ + ptr+= 0xa; \ + if (pfile[0] == 0) { \ + strcpy(dir->name, ptr); \ + } else for (i=0; i<20; i++) { \ + if (pfile[i] == ptr[i]) { \ + dir->name[i] = ptr[i]; \ + if (ptr[i] == 0) break; else continue; } \ + if (pfile[i] == '?') { \ + dir->name[i] = ptr[i]; continue; } \ + if (pfile[i] == '*') { \ + strcpy(dir->name+i, ptr+i); break; } \ + match = 0; break; \ + } \ + SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \ + if (match == 0) continue; \ + dir->size = 8192; \ + v0 = _dir; \ + break; \ + } \ +} + +/* + * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir); + */ + +void psxBios_firstfile() { // 42 + struct DIRENTRY *dir = (struct DIRENTRY *)Ra1; + u32 _dir = a1; + char *ptr; + int i; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0); +#endif + + v0 = 0; + + strcpy(ffile, Ra0); + pfile = ffile+5; + nfile = 1; + if (!strncmp(Ra0, "bu00", 4)) { + bufile(1); + } else if (!strncmp(Ra0, "bu10", 4)) { + bufile(2); + } + + // firstfile() calls _card_read() internally, so deliver it's event + DeliverEvent(0x11, 0x2); + + pc0 = ra; +} + +/* + * struct DIRENTRY* nextfile(struct DIRENTRY *dir); + */ + +void psxBios_nextfile() { // 43 + struct DIRENTRY *dir = (struct DIRENTRY *)Ra0; + u32 _dir = a0; + char *ptr; + int i; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name); +#endif + + v0 = 0; + + if (!strncmp(ffile, "bu00", 4)) { + bufile(1); + } + + if (!strncmp(ffile, "bu10", 4)) { + bufile(2); + } + + pc0 = ra; +} + +#define burename(mcd) { \ + for (i=1; i<16; i++) { \ + int namelen, j, xor = 0; \ + ptr = Mcd##mcd##Data + 128 * i; \ + if ((*ptr & 0xF0) != 0x50) continue; \ + if (strcmp(Ra0+5, ptr+0xa)) continue; \ + namelen = strlen(Ra1+5); \ + memcpy(ptr+0xa, Ra1+5, namelen); \ + memset(ptr+0xa+namelen, 0, 0x75-namelen); \ + for (j=0; j<127; j++) xor^= ptr[j]; \ + ptr[127] = xor; \ + SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \ + v0 = 1; \ + break; \ + } \ +} + +/* + * int rename(char *old, char *new); + */ + +void psxBios_rename() { // 44 + char *ptr; + int i; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1); +#endif + + v0 = 0; + + if (!strncmp(Ra0, "bu00", 4) && !strncmp(Ra1, "bu00", 4)) { + burename(1); + } + + if (!strncmp(Ra0, "bu10", 4) && !strncmp(Ra1, "bu10", 4)) { + burename(2); + } + + pc0 = ra; +} + + +#define budelete(mcd) { \ + for (i=1; i<16; i++) { \ + ptr = Mcd##mcd##Data + 128 * i; \ + if ((*ptr & 0xF0) != 0x50) continue; \ + if (strcmp(Ra0+5, ptr+0xa)) continue; \ + *ptr = (*ptr & 0xf) | 0xA0; \ + SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \ + SysPrintf("delete %s\n", ptr+0xa); \ + v0 = 1; \ + break; \ + } \ +} + +/* + * int delete(char *name); + */ + +void psxBios_delete() { // 45 + char *ptr; + int i; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0); +#endif + + v0 = 0; + + if (!strncmp(Ra0, "bu00", 4)) { + budelete(1); + } + + if (!strncmp(Ra0, "bu10", 4)) { + budelete(2); + } + + pc0 = ra; +} + +void psxBios_InitCARD() { // 4a +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0); +#endif + + CardState = 0; + + pc0 = ra; +} + +void psxBios_StartCARD() { // 4b +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]); +#endif + + if (CardState == 0) CardState = 1; + + pc0 = ra; +} + +void psxBios_StopCARD() { // 4c +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]); +#endif + + if (CardState == 1) CardState = 0; + + pc0 = ra; +} + +void psxBios__card_write() { // 0x4e + int port; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2); +#endif + + card_active_chan = a0; + port = a0 >> 4; + + if (port == 0) { + memcpy(Mcd1Data + a1 * 128, Ra2, 128); + SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128); + } else { + memcpy(Mcd2Data + a1 * 128, Ra2, 128); + SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128); + } + + DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 +// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + + v0 = 1; pc0 = ra; +} + +void psxBios__card_read() { // 0x4f + int port; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]); +#endif + + card_active_chan = a0; + port = a0 >> 4; + + if (port == 0) { + memcpy(Ra2, Mcd1Data + a1 * 128, 128); + } else { + memcpy(Ra2, Mcd2Data + a1 * 128, 128); + } + + DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 +// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + + v0 = 1; pc0 = ra; +} + +void psxBios__new_card() { // 0x50 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]); +#endif + + pc0 = ra; +} + +void psxBios_Krom2RawAdd() { // 0x51 + int i = 0; + + const u32 table_8140[][2] = { + {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8}, + {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a}, + {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c}, + {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266}, + {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e}, + {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a}, + {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c}, + {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca}, + {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8}, + {0xffff, 0} + }; + + const u32 table_889f[][2] = { + {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4}, + {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304}, + {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14}, + {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24}, + {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734}, + {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344}, + {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54}, + {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64}, + {0xffff, 0} + }; + + if (a0 >= 0x8140 && a0 <= 0x84be) { + while (table_8140[i][0] <= a0) i++; + a0 -= table_8140[i - 1][0]; + v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]); + } else if (a0 >= 0x889f && a0 <= 0x9872) { + while (table_889f[i][0] <= a0) i++; + a0 -= table_889f[i - 1][0]; + v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]); + } else { + v0 = 0xffffffff; + } + + pc0 = ra; +} + +void psxBios_GetC0Table() { // 56 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]); +#endif + + v0 = 0x674; pc0 = ra; +} + +void psxBios_GetB0Table() { // 57 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]); +#endif + + v0 = 0x874; pc0 = ra; +} + +void psxBios__card_chan() { // 0x58 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]); +#endif + + v0 = card_active_chan; + pc0 = ra; +} + +void psxBios_ChangeClearPad() { // 5b +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0); +#endif + + pc0 = ra; +} + +/* System calls C0 */ + +/* + * int SysEnqIntRP(int index , long *queue); + */ + +void psxBios_SysEnqIntRP() { // 02 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0); +#endif + + SysIntRP[a0] = a1; + + v0 = 0; pc0 = ra; +} + +/* + * int SysDeqIntRP(int index , long *queue); + */ + +void psxBios_SysDeqIntRP() { // 03 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0); +#endif + + SysIntRP[a0] = 0; + + v0 = 0; pc0 = ra; +} + +void psxBios_ChangeClearRCnt() { // 0a + u32 *ptr; + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1); +#endif + + ptr = (u32*)PSXM((a0 << 2) + 0x8600); + v0 = *ptr; + *ptr = a1; + +// psxRegs.CP0.n.Status|= 0x404; + pc0 = ra; +} + +void psxBios_dummy() { +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1); +#endif + pc0 = ra; +} + +void (*biosA0[256])(); +void (*biosB0[256])(); +void (*biosC0[256])(); + +#include "sjisfont.h" + +void psxBiosInit() { + u32 base, size; + u32 *ptr; + int i; + uLongf len; + + for(i = 0; i < 256; i++) { + biosA0[i] = NULL; + biosB0[i] = NULL; + biosC0[i] = NULL; + } + biosA0[0x3e] = psxBios_puts; + biosA0[0x3f] = psxBios_printf; + + biosB0[0x3d] = psxBios_putchar; + biosB0[0x3f] = psxBios_puts; + + if (!Config.HLE) return; + + for(i = 0; i < 256; i++) { + if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy; + if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy; + if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy; + } + + biosA0[0x00] = psxBios_open; + biosA0[0x01] = psxBios_lseek; + biosA0[0x02] = psxBios_read; + biosA0[0x03] = psxBios_write; + biosA0[0x04] = psxBios_close; + //biosA0[0x05] = psxBios_ioctl; + //biosA0[0x06] = psxBios_exit; + //biosA0[0x07] = psxBios_sys_a0_07; + //biosA0[0x08] = psxBios_getc; + //biosA0[0x09] = psxBios_putc; + //biosA0[0x0a] = psxBios_todigit; + //biosA0[0x0b] = psxBios_atof; + //biosA0[0x0c] = psxBios_strtoul; + //biosA0[0x0d] = psxBios_strtol; + biosA0[0x0e] = psxBios_abs; + biosA0[0x0f] = psxBios_labs; + biosA0[0x10] = psxBios_atoi; + biosA0[0x11] = psxBios_atol; + //biosA0[0x12] = psxBios_atob; + biosA0[0x13] = psxBios_setjmp; + biosA0[0x14] = psxBios_longjmp; + biosA0[0x15] = psxBios_strcat; + biosA0[0x16] = psxBios_strncat; + biosA0[0x17] = psxBios_strcmp; + biosA0[0x18] = psxBios_strncmp; + biosA0[0x19] = psxBios_strcpy; + biosA0[0x1a] = psxBios_strncpy; + biosA0[0x1b] = psxBios_strlen; + biosA0[0x1c] = psxBios_index; + biosA0[0x1d] = psxBios_rindex; + biosA0[0x1e] = psxBios_strchr; + biosA0[0x1f] = psxBios_strrchr; + biosA0[0x20] = psxBios_strpbrk; + biosA0[0x21] = psxBios_strspn; + biosA0[0x22] = psxBios_strcspn; + biosA0[0x23] = psxBios_strtok; + biosA0[0x24] = psxBios_strstr; + biosA0[0x25] = psxBios_toupper; + biosA0[0x26] = psxBios_tolower; + biosA0[0x27] = psxBios_bcopy; + biosA0[0x28] = psxBios_bzero; + biosA0[0x29] = psxBios_bcmp; + biosA0[0x2a] = psxBios_memcpy; + biosA0[0x2b] = psxBios_memset; + biosA0[0x2c] = psxBios_memmove; + biosA0[0x2d] = psxBios_memcmp; + biosA0[0x2e] = psxBios_memchr; + biosA0[0x2f] = psxBios_rand; + biosA0[0x30] = psxBios_srand; + biosA0[0x31] = psxBios_qsort; + //biosA0[0x32] = psxBios_strtod; + biosA0[0x33] = psxBios_malloc; + biosA0[0x34] = psxBios_free; + //biosA0[0x35] = psxBios_lsearch; + //biosA0[0x36] = psxBios_bsearch; + biosA0[0x37] = psxBios_calloc; + biosA0[0x38] = psxBios_realloc; + biosA0[0x39] = psxBios_InitHeap; + //biosA0[0x3a] = psxBios__exit; + biosA0[0x3b] = psxBios_getchar; + biosA0[0x3c] = psxBios_putchar; + //biosA0[0x3d] = psxBios_gets; + //biosA0[0x40] = psxBios_sys_a0_40; + //biosA0[0x41] = psxBios_LoadTest; + biosA0[0x42] = psxBios_Load; + biosA0[0x43] = psxBios_Exec; + biosA0[0x44] = psxBios_FlushCache; + //biosA0[0x45] = psxBios_InstallInterruptHandler; + biosA0[0x46] = psxBios_GPU_dw; + biosA0[0x47] = psxBios_mem2vram; + biosA0[0x48] = psxBios_SendGPU; + biosA0[0x49] = psxBios_GPU_cw; + biosA0[0x4a] = psxBios_GPU_cwb; + biosA0[0x4b] = psxBios_GPU_SendPackets; + biosA0[0x4c] = psxBios_sys_a0_4c; + biosA0[0x4d] = psxBios_GPU_GetGPUStatus; + //biosA0[0x4e] = psxBios_GPU_sync; + //biosA0[0x4f] = psxBios_sys_a0_4f; + //biosA0[0x50] = psxBios_sys_a0_50; + biosA0[0x51] = psxBios_LoadExec; + //biosA0[0x52] = psxBios_GetSysSp; + //biosA0[0x53] = psxBios_sys_a0_53; + //biosA0[0x54] = psxBios__96_init_a54; + //biosA0[0x55] = psxBios__bu_init_a55; + //biosA0[0x56] = psxBios__96_remove_a56; + //biosA0[0x57] = psxBios_sys_a0_57; + //biosA0[0x58] = psxBios_sys_a0_58; + //biosA0[0x59] = psxBios_sys_a0_59; + //biosA0[0x5a] = psxBios_sys_a0_5a; + //biosA0[0x5b] = psxBios_dev_tty_init; + //biosA0[0x5c] = psxBios_dev_tty_open; + //biosA0[0x5d] = psxBios_sys_a0_5d; + //biosA0[0x5e] = psxBios_dev_tty_ioctl; + //biosA0[0x5f] = psxBios_dev_cd_open; + //biosA0[0x60] = psxBios_dev_cd_read; + //biosA0[0x61] = psxBios_dev_cd_close; + //biosA0[0x62] = psxBios_dev_cd_firstfile; + //biosA0[0x63] = psxBios_dev_cd_nextfile; + //biosA0[0x64] = psxBios_dev_cd_chdir; + //biosA0[0x65] = psxBios_dev_card_open; + //biosA0[0x66] = psxBios_dev_card_read; + //biosA0[0x67] = psxBios_dev_card_write; + //biosA0[0x68] = psxBios_dev_card_close; + //biosA0[0x69] = psxBios_dev_card_firstfile; + //biosA0[0x6a] = psxBios_dev_card_nextfile; + //biosA0[0x6b] = psxBios_dev_card_erase; + //biosA0[0x6c] = psxBios_dev_card_undelete; + //biosA0[0x6d] = psxBios_dev_card_format; + //biosA0[0x6e] = psxBios_dev_card_rename; + //biosA0[0x6f] = psxBios_dev_card_6f; + biosA0[0x70] = psxBios__bu_init; + biosA0[0x71] = psxBios__96_init; + biosA0[0x72] = psxBios__96_remove; + //biosA0[0x73] = psxBios_sys_a0_73; + //biosA0[0x74] = psxBios_sys_a0_74; + //biosA0[0x75] = psxBios_sys_a0_75; + //biosA0[0x76] = psxBios_sys_a0_76; + //biosA0[0x77] = psxBios_sys_a0_77; + //biosA0[0x78] = psxBios__96_CdSeekL; + //biosA0[0x79] = psxBios_sys_a0_79; + //biosA0[0x7a] = psxBios_sys_a0_7a; + //biosA0[0x7b] = psxBios_sys_a0_7b; + //biosA0[0x7c] = psxBios__96_CdGetStatus; + //biosA0[0x7d] = psxBios_sys_a0_7d; + //biosA0[0x7e] = psxBios__96_CdRead; + //biosA0[0x7f] = psxBios_sys_a0_7f; + //biosA0[0x80] = psxBios_sys_a0_80; + //biosA0[0x81] = psxBios_sys_a0_81; + //biosA0[0x82] = psxBios_sys_a0_82; + //biosA0[0x83] = psxBios_sys_a0_83; + //biosA0[0x84] = psxBios_sys_a0_84; + //biosA0[0x85] = psxBios__96_CdStop; + //biosA0[0x86] = psxBios_sys_a0_86; + //biosA0[0x87] = psxBios_sys_a0_87; + //biosA0[0x88] = psxBios_sys_a0_88; + //biosA0[0x89] = psxBios_sys_a0_89; + //biosA0[0x8a] = psxBios_sys_a0_8a; + //biosA0[0x8b] = psxBios_sys_a0_8b; + //biosA0[0x8c] = psxBios_sys_a0_8c; + //biosA0[0x8d] = psxBios_sys_a0_8d; + //biosA0[0x8e] = psxBios_sys_a0_8e; + //biosA0[0x8f] = psxBios_sys_a0_8f; + //biosA0[0x90] = psxBios_sys_a0_90; + //biosA0[0x91] = psxBios_sys_a0_91; + //biosA0[0x92] = psxBios_sys_a0_92; + //biosA0[0x93] = psxBios_sys_a0_93; + //biosA0[0x94] = psxBios_sys_a0_94; + //biosA0[0x95] = psxBios_sys_a0_95; + //biosA0[0x96] = psxBios_AddCDROMDevice; + //biosA0[0x97] = psxBios_AddMemCardDevide; + //biosA0[0x98] = psxBios_DisableKernelIORedirection; + //biosA0[0x99] = psxBios_EnableKernelIORedirection; + //biosA0[0x9a] = psxBios_sys_a0_9a; + //biosA0[0x9b] = psxBios_sys_a0_9b; + //biosA0[0x9c] = psxBios_SetConf; + //biosA0[0x9d] = psxBios_GetConf; + //biosA0[0x9e] = psxBios_sys_a0_9e; + biosA0[0x9f] = psxBios_SetMem; + //biosA0[0xa0] = psxBios__boot; + //biosA0[0xa1] = psxBios_SystemError; + //biosA0[0xa2] = psxBios_EnqueueCdIntr; + //biosA0[0xa3] = psxBios_DequeueCdIntr; + //biosA0[0xa4] = psxBios_sys_a0_a4; + //biosA0[0xa5] = psxBios_ReadSector; + //biosA0[0xa6] = psxBios_get_cd_status; + //biosA0[0xa7] = psxBios_bufs_cb_0; + //biosA0[0xa8] = psxBios_bufs_cb_1; + //biosA0[0xa9] = psxBios_bufs_cb_2; + //biosA0[0xaa] = psxBios_bufs_cb_3; + biosA0[0xab] = psxBios__card_info; + biosA0[0xac] = psxBios__card_load; + //biosA0[0axd] = psxBios__card_auto; + //biosA0[0xae] = psxBios_bufs_cd_4; + //biosA0[0xaf] = psxBios_sys_a0_af; + //biosA0[0xb0] = psxBios_sys_a0_b0; + //biosA0[0xb1] = psxBios_sys_a0_b1; + //biosA0[0xb2] = psxBios_do_a_long_jmp + //biosA0[0xb3] = psxBios_sys_a0_b3; + //biosA0[0xb4] = psxBios_sub_function; +//*******************B0 CALLS**************************** + //biosB0[0x00] = psxBios_SysMalloc; + //biosB0[0x01] = psxBios_sys_b0_01; + biosB0[0x02] = psxBios_SetRCnt; + biosB0[0x03] = psxBios_GetRCnt; + biosB0[0x04] = psxBios_StartRCnt; + biosB0[0x05] = psxBios_StopRCnt; + biosB0[0x06] = psxBios_ResetRCnt; + biosB0[0x07] = psxBios_DeliverEvent; + biosB0[0x08] = psxBios_OpenEvent; + biosB0[0x09] = psxBios_CloseEvent; + biosB0[0x0a] = psxBios_WaitEvent; + biosB0[0x0b] = psxBios_TestEvent; + biosB0[0x0c] = psxBios_EnableEvent; + biosB0[0x0d] = psxBios_DisableEvent; + biosB0[0x0e] = psxBios_OpenTh; + biosB0[0x0f] = psxBios_CloseTh; + biosB0[0x10] = psxBios_ChangeTh; + //biosB0[0x11] = psxBios_psxBios_b0_11; + biosB0[0x12] = psxBios_InitPAD; + biosB0[0x13] = psxBios_StartPAD; + biosB0[0x14] = psxBios_StopPAD; + biosB0[0x15] = psxBios_PAD_init; + biosB0[0x16] = psxBios_PAD_dr; + biosB0[0x17] = psxBios_ReturnFromException; + biosB0[0x18] = psxBios_ResetEntryInt; + biosB0[0x19] = psxBios_HookEntryInt; + //biosB0[0x1a] = psxBios_sys_b0_1a; + //biosB0[0x1b] = psxBios_sys_b0_1b; + //biosB0[0x1c] = psxBios_sys_b0_1c; + //biosB0[0x1d] = psxBios_sys_b0_1d; + //biosB0[0x1e] = psxBios_sys_b0_1e; + //biosB0[0x1f] = psxBios_sys_b0_1f; + biosB0[0x20] = psxBios_UnDeliverEvent; + //biosB0[0x21] = psxBios_sys_b0_21; + //biosB0[0x22] = psxBios_sys_b0_22; + //biosB0[0x23] = psxBios_sys_b0_23; + //biosB0[0x24] = psxBios_sys_b0_24; + //biosB0[0x25] = psxBios_sys_b0_25; + //biosB0[0x26] = psxBios_sys_b0_26; + //biosB0[0x27] = psxBios_sys_b0_27; + //biosB0[0x28] = psxBios_sys_b0_28; + //biosB0[0x29] = psxBios_sys_b0_29; + //biosB0[0x2a] = psxBios_sys_b0_2a; + //biosB0[0x2b] = psxBios_sys_b0_2b; + //biosB0[0x2c] = psxBios_sys_b0_2c; + //biosB0[0x2d] = psxBios_sys_b0_2d; + //biosB0[0x2e] = psxBios_sys_b0_2e; + //biosB0[0x2f] = psxBios_sys_b0_2f; + //biosB0[0x30] = psxBios_sys_b0_30; + //biosB0[0x31] = psxBios_sys_b0_31; + biosB0[0x32] = psxBios_open; + biosB0[0x33] = psxBios_lseek; + biosB0[0x34] = psxBios_read; + biosB0[0x35] = psxBios_write; + biosB0[0x36] = psxBios_close; + //biosB0[0x37] = psxBios_ioctl; + //biosB0[0x38] = psxBios_exit; + //biosB0[0x39] = psxBios_sys_b0_39; + //biosB0[0x3a] = psxBios_getc; + //biosB0[0x3b] = psxBios_putc; + biosB0[0x3c] = psxBios_getchar; + //biosB0[0x3e] = psxBios_gets; + //biosB0[0x40] = psxBios_cd; + //biosB0[0x41] = psxBios_format; + biosB0[0x42] = psxBios_firstfile; + biosB0[0x43] = psxBios_nextfile; + biosB0[0x44] = psxBios_rename; + biosB0[0x45] = psxBios_delete; + //biosB0[0x46] = psxBios_undelete; + //biosB0[0x47] = psxBios_AddDevice; + //biosB0[0x48] = psxBios_RemoteDevice; + //biosB0[0x49] = psxBios_PrintInstalledDevices; + biosB0[0x4a] = psxBios_InitCARD; + biosB0[0x4b] = psxBios_StartCARD; + biosB0[0x4c] = psxBios_StopCARD; + //biosB0[0x4d] = psxBios_sys_b0_4d; + biosB0[0x4e] = psxBios__card_write; + biosB0[0x4f] = psxBios__card_read; + biosB0[0x50] = psxBios__new_card; + biosB0[0x51] = psxBios_Krom2RawAdd; + //biosB0[0x52] = psxBios_sys_b0_52; + //biosB0[0x53] = psxBios_sys_b0_53; + //biosB0[0x54] = psxBios__get_errno; + //biosB0[0x55] = psxBios__get_error; + biosB0[0x56] = psxBios_GetC0Table; + biosB0[0x57] = psxBios_GetB0Table; + biosB0[0x58] = psxBios__card_chan; + //biosB0[0x59] = psxBios_sys_b0_59; + //biosB0[0x5a] = psxBios_sys_b0_5a; + biosB0[0x5b] = psxBios_ChangeClearPad; + //biosB0[0x5c] = psxBios__card_status; + //biosB0[0x5d] = psxBios__card_wait; +//*******************C0 CALLS**************************** + //biosC0[0x00] = psxBios_InitRCnt; + //biosC0[0x01] = psxBios_InitException; + biosC0[0x02] = psxBios_SysEnqIntRP; + biosC0[0x03] = psxBios_SysDeqIntRP; + //biosC0[0x04] = psxBios_get_free_EvCB_slot; + //biosC0[0x05] = psxBios_get_free_TCB_slot; + //biosC0[0x06] = psxBios_ExceptionHandler; + //biosC0[0x07] = psxBios_InstallExeptionHandler; + //biosC0[0x08] = psxBios_SysInitMemory; + //biosC0[0x09] = psxBios_SysInitKMem; + biosC0[0x0a] = psxBios_ChangeClearRCnt; + //biosC0[0x0b] = psxBios_SystemError; + //biosC0[0x0c] = psxBios_InitDefInt; + //biosC0[0x0d] = psxBios_sys_c0_0d; + //biosC0[0x0e] = psxBios_sys_c0_0e; + //biosC0[0x0f] = psxBios_sys_c0_0f; + //biosC0[0x10] = psxBios_sys_c0_10; + //biosC0[0x11] = psxBios_sys_c0_11; + //biosC0[0x12] = psxBios_InstallDevices; + //biosC0[0x13] = psxBios_FlushStfInOutPut; + //biosC0[0x14] = psxBios_sys_c0_14; + //biosC0[0x15] = psxBios__cdevinput; + //biosC0[0x16] = psxBios__cdevscan; + //biosC0[0x17] = psxBios__circgetc; + //biosC0[0x18] = psxBios__circputc; + //biosC0[0x19] = psxBios_ioabort; + //biosC0[0x1a] = psxBios_sys_c0_1a + //biosC0[0x1b] = psxBios_KernelRedirect; + //biosC0[0x1c] = psxBios_PatchAOTable; +//************** THE END *************************************** +/**/ + base = 0x1000; + size = sizeof(EvCB) * 32; + Event = (void *)&psxR[base]; base += size * 6; + memset(Event, 0, size * 6); + HwEV = Event; + EvEV = Event + 32; + RcEV = Event + 32 * 2; + UeEV = Event + 32 * 3; + SwEV = Event + 32 * 4; + ThEV = Event + 32 * 5; + + ptr = (u32 *)&psxM[0x0874]; // b0 table + ptr[0] = SWAPu32(0x4c54 - 0x884); + + ptr = (u32 *)&psxM[0x0674]; // c0 table + ptr[6] = SWAPu32(0xc80); + + memset(SysIntRP, 0, sizeof(SysIntRP)); + memset(Thread, 0, sizeof(Thread)); + Thread[0].status = 2; // main thread + + jmp_int = NULL; + pad_buf = NULL; + pad_buf1 = NULL; + pad_buf2 = NULL; + pad_buf1len = pad_buf2len = 0; + heap_addr = NULL; + heap_end = NULL; + CardState = -1; + CurThread = 0; + memset(FDesc, 0, sizeof(FDesc)); + card_active_chan = 0; + + psxMu32ref(0x0150) = SWAPu32(0x160); + psxMu32ref(0x0154) = SWAPu32(0x320); + psxMu32ref(0x0160) = SWAPu32(0x248); + strcpy((char *)&psxM[0x248], "bu"); +/* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004); + psxMu32ref(0x0cf0) = SWAPu32(0x3c020000); + psxMu32ref(0x0cf4) = SWAPu32(0x2442641c); + psxMu32ref(0x09e0) = SWAPu32(0x43d0); + psxMu32ref(0x4d98) = SWAPu32(0x946f000a); +*/ + // opcode HLE + psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4); + psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0); + psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1); + psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2); + psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3); + psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0); + psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5); + psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0); + psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0); + psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0); + + // initial stack pointer for BIOS interrupt + psxMu32ref(0x6c80) = SWAPu32(0x000085c8); + + // initial RNG seed + psxMu32ref(0x9010) = SWAPu32(0xac20cc00); + + // fonts + len = 0x80000 - 0x66000; + uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140)); + len = 0x80000 - 0x69d68; + uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f)); + + // memory size 2 MB + psxHu32ref(0x1060) = SWAPu32(0x00000b88); + + hleSoftCall = FALSE; +} + +void psxBiosShutdown() { +} + +#define psxBios_PADpoll(pad) { \ + PAD##pad##_startPoll(pad); \ + pad_buf##pad[0] = 0; \ + pad_buf##pad[1] = PAD##pad##_poll(0x42); \ + if (!(pad_buf##pad[1] & 0x0f)) { \ + bufcount = 32; \ + } else { \ + bufcount = (pad_buf##pad[1] & 0x0f) * 2; \ + } \ + PAD##pad##_poll(0); \ + i = 2; \ + while (bufcount--) { \ + pad_buf##pad[i++] = PAD##pad##_poll(0); \ + } \ +} + +void biosInterrupt() { + int i, bufcount; + +// if (psxHu32(0x1070) & 0x1) { // Vsync + if (pad_buf != NULL) { + u32 *buf = (u32*)pad_buf; + + if (!Config.UseNet) { + PAD1_startPoll(1); + if (PAD1_poll(0x42) == 0x23) { + PAD1_poll(0); + *buf = PAD1_poll(0) << 8; + *buf |= PAD1_poll(0); + PAD1_poll(0); + *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0); + *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0); + } else { + PAD1_poll(0); + *buf = PAD1_poll(0) << 8; + *buf|= PAD1_poll(0); + } + + PAD2_startPoll(2); + if (PAD2_poll(0x42) == 0x23) { + PAD2_poll(0); + *buf |= PAD2_poll(0) << 24; + *buf |= PAD2_poll(0) << 16; + PAD2_poll(0); + *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0); + *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0); + } else { + PAD2_poll(0); + *buf |= PAD2_poll(0) << 24; + *buf |= PAD2_poll(0) << 16; + } + } else { + u16 data; + + PAD1_startPoll(1); + PAD1_poll(0x42); + PAD1_poll(0); + data = PAD1_poll(0) << 8; + data |= PAD1_poll(0); + + if (NET_sendPadData(&data, 2) == -1) + netError(); + + if (NET_recvPadData(&((u16*)buf)[0], 1) == -1) + netError(); + if (NET_recvPadData(&((u16*)buf)[1], 2) == -1) + netError(); + } + } + if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) { + psxBios_PADpoll(1); + + if (NET_sendPadData(pad_buf1, i) == -1) + netError(); + + if (NET_recvPadData(pad_buf1, 1) == -1) + netError(); + if (NET_recvPadData(pad_buf2, 2) == -1) + netError(); + } else { + if (pad_buf1) { + psxBios_PADpoll(1); + } + + if (pad_buf2) { + psxBios_PADpoll(2); + } + } + + if (psxHu32(0x1070) & 0x1) { // Vsync + if (RcEV[3][1].status == EvStACTIVE) { + softCall(RcEV[3][1].fhandler); +// hwWrite32(0x1f801070, ~(1)); + } + } + + if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2 + int i; + + for (i = 0; i < 3; i++) { + if (psxHu32(0x1070) & (1 << (i + 4))) { + if (RcEV[i][1].status == EvStACTIVE) { + softCall(RcEV[i][1].fhandler); + } + psxHwWrite32(0x1f801070, ~(1 << (i + 4))); + } + } + } +} + +void psxBiosException() { + int i; + + switch (psxRegs.CP0.n.Cause & 0x3c) { + case 0x00: // Interrupt +#ifdef PSXCPU_LOG +// PSXCPU_LOG("interrupt\n"); +#endif + SaveRegs(); + + sp = psxMu32(0x6c80); // create new stack for interrupt handlers + + biosInterrupt(); + + for (i = 0; i < 8; i++) { + if (SysIntRP[i]) { + u32 *queue = (u32 *)PSXM(SysIntRP[i]); + + s0 = queue[2]; + softCall(queue[1]); + } + } + + if (jmp_int != NULL) { + int i; + + psxHwWrite32(0x1f801070, 0xffffffff); + + ra = jmp_int[0]; + sp = jmp_int[1]; + fp = jmp_int[2]; + for (i = 0; i < 8; i++) // s0-s7 + psxRegs.GPR.r[16 + i] = jmp_int[3 + i]; + gp = jmp_int[11]; + + v0 = 1; + pc0 = ra; + return; + } + psxHwWrite16(0x1f801070, 0); + break; + + case 0x20: // Syscall +#ifdef PSXCPU_LOG + PSXCPU_LOG("syscall exp %x\n", a0); +#endif + switch (a0) { + case 1: // EnterCritical - disable irq's + psxRegs.CP0.n.Status &= ~0x404; +v0=1; // HDHOSHY experimental patch: Spongebob, Coldblood, fearEffect, Medievil2, Martian Gothic + break; + + case 2: // ExitCritical - enable irq's + psxRegs.CP0.n.Status |= 0x404; + break; + } + pc0 = psxRegs.CP0.n.EPC + 4; + + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); + return; + + default: +#ifdef PSXCPU_LOG + PSXCPU_LOG("unknown bios exception!\n"); +#endif + break; + } + + pc0 = psxRegs.CP0.n.EPC; + if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4; + + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +} + +#define bfreeze(ptr, size) { \ + if (Mode == 1) memcpy(&psxR[base], ptr, size); \ + if (Mode == 0) memcpy(ptr, &psxR[base], size); \ + base += size; \ +} + +#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr)) +#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr)) + +#define bfreezepsxMptr(ptr, type) { \ + if (Mode == 1) { \ + if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \ + else psxRu32ref(base) = 0; \ + } else { \ + if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \ + else (ptr) = NULL; \ + } \ + base += sizeof(u32); \ +} + +void psxBiosFreeze(int Mode) { + u32 base = 0x40000; + + bfreezepsxMptr(jmp_int, u32); + bfreezepsxMptr(pad_buf, int); + bfreezepsxMptr(pad_buf1, char); + bfreezepsxMptr(pad_buf2, char); + bfreezepsxMptr(heap_addr, u32); + bfreezel(&pad_buf1len); + bfreezel(&pad_buf2len); + bfreezes(regs); + bfreezes(SysIntRP); + bfreezel(&CardState); + bfreezes(Thread); + bfreezel(&CurThread); + bfreezes(FDesc); + bfreezel(&card_active_chan); +} diff --git a/libpcsxcore/psxbios.h b/libpcsxcore/psxbios.h index a5630b19..fed81189 100644..100755 --- a/libpcsxcore/psxbios.h +++ b/libpcsxcore/psxbios.h @@ -1,51 +1,51 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#ifndef __PSXBIOS_H__
-#define __PSXBIOS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "psxcommon.h"
-#include "r3000a.h"
-#include "psxmem.h"
-#include "misc.h"
-#include "sio.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])();
-
-extern boolean hleSoftCall;
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef __PSXBIOS_H__ +#define __PSXBIOS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxmem.h" +#include "misc.h" +#include "sio.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])(); + +extern boolean hleSoftCall; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h index e1d4b0c9..45754a72 100644..100755 --- a/libpcsxcore/psxcommon.h +++ b/libpcsxcore/psxcommon.h @@ -1,192 +1,192 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* This file contains common definitions and includes for all parts of the
-* emulator core.
-*/
-
-#ifndef __PSXCOMMON_H__
-#define __PSXCOMMON_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-
-// System includes
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <math.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <zlib.h>
-
-// Define types
-typedef int8_t s8;
-typedef int16_t s16;
-typedef int32_t s32;
-typedef int64_t s64;
-typedef intptr_t sptr;
-
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-typedef uintptr_t uptr;
-
-typedef uint8_t boolean;
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-// Local includes
-#include "system.h"
-#include "debug.h"
-
-#if defined (__LINUX__) || defined (__MACOSX__)
-#define strnicmp strncasecmp
-#endif
-#define __inline inline
-
-// Enables NLS/internationalization if active
-#ifdef ENABLE_NLS
-
-#include <libintl.h>
-
-#undef _
-#define _(String) gettext(String)
-#ifdef gettext_noop
-# define N_(String) gettext_noop (String)
-#else
-# define N_(String) (String)
-#endif
-
-//If running under Mac OS X, use the Localizable.strings file instead.
-#elif defined(_MACOSX)
-#ifdef PCSXRCORE
-extern const char* Pcsxr_locale_text(char* toloc);
-#define _(String) Pcsxr_locale_text(String)
-#define N_(String) String
-#else
-#ifndef PCSXRPLUG
-#warning please define the plug being built to use Mac OS X localization!
-#define _(msgid) msgid
-#define N_(msgid) msgid
-#else
-//Kludge to get the preprocessor to accept PCSXRPLUG as a variable.
-#define PLUGLOC_x(x,y) x ## y
-#define PLUGLOC_y(x,y) PLUGLOC_x(x,y)
-#define PLUGLOC PLUGLOC_y(PCSXRPLUG,_locale_text)
-extern const char* PLUGLOC(char* toloc);
-#define _(String) PLUGLOC(String)
-#define N_(String) String
-#endif
-#endif
-#else
-
-#define _(msgid) msgid
-#define N_(msgid) msgid
-
-#endif
-
-extern FILE *emuLog;
-extern int Log;
-
-void __Log(char *fmt, ...);
-
-typedef struct {
- char Gpu[MAXPATHLEN];
- char Spu[MAXPATHLEN];
- char Cdr[MAXPATHLEN];
- char Pad1[MAXPATHLEN];
- char Pad2[MAXPATHLEN];
- char Net[MAXPATHLEN];
- char Sio1[MAXPATHLEN];
- char Mcd1[MAXPATHLEN];
- char Mcd2[MAXPATHLEN];
- char Bios[MAXPATHLEN];
- char BiosDir[MAXPATHLEN];
- char PluginsDir[MAXPATHLEN];
- char PatchesDir[MAXPATHLEN];
- boolean Xa;
- boolean Sio;
- boolean Mdec;
- boolean PsxAuto;
- boolean Cdda;
- boolean HLE;
- boolean SlowBoot;
- boolean Debug;
- boolean PsxOut;
- boolean SpuIrq;
- boolean RCntFix;
- boolean UseNet;
- boolean VSyncWA;
- boolean Widescreen;
- u8 Cpu; // CPU_DYNAREC or CPU_INTERPRETER
- u8 PsxType; // PSX_TYPE_NTSC or PSX_TYPE_PAL
-#ifdef _WIN32
- char Lang[256];
-#endif
-} PcsxConfig;
-
-extern PcsxConfig Config;
-extern boolean NetOpened;
-
-#define gzfreeze(ptr, size) { \
- if (Mode == 1) gzwrite(f, ptr, size); \
- if (Mode == 0) gzread(f, ptr, size); \
-}
-
-// Make the timing events trigger faster as we are currently assuming everything
-// takes one cycle, which is not the case on real hardware.
-// FIXME: Count the proper cycle and get rid of this
-#define BIAS 2
-#define PSXCLK 33868800 /* 33.8688 MHz */
-
-enum {
- PSX_TYPE_NTSC = 0,
- PSX_TYPE_PAL
-}; // PSX Types
-
-enum {
- CPU_DYNAREC = 0,
- CPU_INTERPRETER
-}; // CPU Types
-
-int EmuInit();
-void EmuReset();
-void EmuShutdown();
-void EmuUpdate();
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* This file contains common definitions and includes for all parts of the +* emulator core. +*/ + +#ifndef __PSXCOMMON_H__ +#define __PSXCOMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" + +// System includes +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#include <ctype.h> +#include <sys/types.h> +#include <assert.h> +#include <zlib.h> + +// Define types +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef intptr_t sptr; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef uintptr_t uptr; + +typedef uint8_t boolean; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +// Local includes +#include "system.h" +#include "debug.h" + +#if defined (__LINUX__) || defined (__MACOSX__) +#define strnicmp strncasecmp +#endif +#define __inline inline + +// Enables NLS/internationalization if active +#ifdef ENABLE_NLS + +#include <libintl.h> + +#undef _ +#define _(String) gettext(String) +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +# define N_(String) (String) +#endif + +//If running under Mac OS X, use the Localizable.strings file instead. +#elif defined(_MACOSX) +#ifdef PCSXRCORE +extern const char* Pcsxr_locale_text(char* toloc); +#define _(String) Pcsxr_locale_text(String) +#define N_(String) String +#else +#ifndef PCSXRPLUG +#warning please define the plug being built to use Mac OS X localization! +#define _(msgid) msgid +#define N_(msgid) msgid +#else +//Kludge to get the preprocessor to accept PCSXRPLUG as a variable. +#define PLUGLOC_x(x,y) x ## y +#define PLUGLOC_y(x,y) PLUGLOC_x(x,y) +#define PLUGLOC PLUGLOC_y(PCSXRPLUG,_locale_text) +extern const char* PLUGLOC(char* toloc); +#define _(String) PLUGLOC(String) +#define N_(String) String +#endif +#endif +#else + +#define _(msgid) msgid +#define N_(msgid) msgid + +#endif + +extern FILE *emuLog; +extern int Log; + +void __Log(char *fmt, ...); + +typedef struct { + char Gpu[MAXPATHLEN]; + char Spu[MAXPATHLEN]; + char Cdr[MAXPATHLEN]; + char Pad1[MAXPATHLEN]; + char Pad2[MAXPATHLEN]; + char Net[MAXPATHLEN]; + char Sio1[MAXPATHLEN]; + char Mcd1[MAXPATHLEN]; + char Mcd2[MAXPATHLEN]; + char Bios[MAXPATHLEN]; + char BiosDir[MAXPATHLEN]; + char PluginsDir[MAXPATHLEN]; + char PatchesDir[MAXPATHLEN]; + boolean Xa; + boolean Sio; + boolean Mdec; + boolean PsxAuto; + boolean Cdda; + boolean HLE; + boolean SlowBoot; + boolean Debug; + boolean PsxOut; + boolean SpuIrq; + boolean RCntFix; + boolean UseNet; + boolean VSyncWA; + boolean Widescreen; + u8 Cpu; // CPU_DYNAREC or CPU_INTERPRETER + u8 PsxType; // PSX_TYPE_NTSC or PSX_TYPE_PAL +#ifdef _WIN32 + char Lang[256]; +#endif +} PcsxConfig; + +extern PcsxConfig Config; +extern boolean NetOpened; + +#define gzfreeze(ptr, size) { \ + if (Mode == 1) gzwrite(f, ptr, size); \ + if (Mode == 0) gzread(f, ptr, size); \ +} + +// Make the timing events trigger faster as we are currently assuming everything +// takes one cycle, which is not the case on real hardware. +// FIXME: Count the proper cycle and get rid of this +#define BIAS 2 +#define PSXCLK 33868800 /* 33.8688 MHz */ + +enum { + PSX_TYPE_NTSC = 0, + PSX_TYPE_PAL +}; // PSX Types + +enum { + CPU_DYNAREC = 0, + CPU_INTERPRETER +}; // CPU Types + +int EmuInit(); +void EmuReset(); +void EmuShutdown(); +void EmuUpdate(); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index d573d446..631c21f0 100644..100755 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -1,486 +1,486 @@ -/***************************************************************************
- * Copyright (C) 2010 by Blade_Arma *
- * *
- * 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
- * Internal PSX counters.
- */
-
-#include "psxcounters.h"
-
-/******************************************************************************/
-
-typedef struct Rcnt
-{
- u16 mode, target;
- u32 rate, irq, counterState, irqState;
- u32 cycle, cycleStart;
-} Rcnt;
-
-enum
-{
- Rc0Gate = 0x0001, // 0 not implemented
- Rc1Gate = 0x0001, // 0 not implemented
- Rc2Disable = 0x0001, // 0 partially implemented
- RcUnknown1 = 0x0002, // 1 ?
- RcUnknown2 = 0x0004, // 2 ?
- RcCountToTarget = 0x0008, // 3
- RcIrqOnTarget = 0x0010, // 4
- RcIrqOnOverflow = 0x0020, // 5
- RcIrqRegenerate = 0x0040, // 6
- RcUnknown7 = 0x0080, // 7 ?
- Rc0PixelClock = 0x0100, // 8 fake implementation
- Rc1HSyncClock = 0x0100, // 8
- Rc2Unknown8 = 0x0100, // 8 ?
- Rc0Unknown9 = 0x0200, // 9 ?
- Rc1Unknown9 = 0x0200, // 9 ?
- Rc2OneEighthClock = 0x0200, // 9
- RcUnknown10 = 0x0400, // 10 ?
- RcCountEqTarget = 0x0800, // 11
- RcOverflow = 0x1000, // 12
- RcUnknown13 = 0x2000, // 13 ? (always zero)
- RcUnknown14 = 0x4000, // 14 ? (always zero)
- RcUnknown15 = 0x8000, // 15 ? (always zero)
-};
-
-#define CounterQuantity ( 4 )
-//static const u32 CounterQuantity = 4;
-
-static const u32 CountToOverflow = 0;
-static const u32 CountToTarget = 1;
-
-static const u32 FrameRate[] = { 60, 50 };
-//static const u32 VBlankStart[] = { 240, 256 };
-static const u32 VBlankStart[] = { 243, 256 };
-static const u32 HSyncTotal[] = { 263, 313 };
-static const u32 SpuUpdInterval[] = { 23, 22 };
-
-static const s32 VerboseLevel = 0;
-
-/******************************************************************************/
-
-static Rcnt rcnts[ CounterQuantity ];
-
-static u32 hSyncCount = 0;
-static u32 spuSyncCount = 0;
-
-u32 psxNextCounter = 0, psxNextsCounter = 0;
-
-/******************************************************************************/
-
-static inline
-void setIrq( u32 irq )
-{
- psxHu32ref(0x1070) |= SWAPu32(irq);
-}
-
-static
-void verboseLog( s32 level, const char *str, ... )
-{
- if( level <= VerboseLevel )
- {
- va_list va;
- char buf[ 4096 ];
-
- va_start( va, str );
- vsnprintf( buf, sizeof(buf), str, va );
- va_end( va );
-
- printf( "%s", buf );
- fflush( stdout );
- }
-}
-
-/******************************************************************************/
-
-static inline
-void _psxRcntWcount( u32 index, u32 value )
-{
- if( value > 0xffff )
- {
- verboseLog( 1, "[RCNT %i] wcount > 0xffff: %x\n", index, value );
- value &= 0xffff;
- }
-
- rcnts[index].cycleStart = psxRegs.cycle;
- rcnts[index].cycleStart -= value * rcnts[index].rate;
-
- // TODO: <=.
- if( value < rcnts[index].target )
- {
- rcnts[index].cycle = rcnts[index].target * rcnts[index].rate;
- rcnts[index].counterState = CountToTarget;
- }
- else
- {
- rcnts[index].cycle = 0xffff * rcnts[index].rate;
- rcnts[index].counterState = CountToOverflow;
- }
-}
-
-static inline
-u32 _psxRcntRcount( u32 index )
-{
- u32 count;
-
- count = psxRegs.cycle;
- count -= rcnts[index].cycleStart;
- count /= rcnts[index].rate;
-
- if( count > 0xffff )
- {
- verboseLog( 1, "[RCNT %i] rcount > 0xffff: %x\n", index, count );
- count &= 0xffff;
- }
-
- return count;
-}
-
-/******************************************************************************/
-
-static
-void psxRcntSet()
-{
- s32 countToUpdate;
- u32 i;
-
- psxNextsCounter = psxRegs.cycle;
- psxNextCounter = 0x7fffffff;
-
- for( i = 0; i < CounterQuantity; ++i )
- {
- countToUpdate = rcnts[i].cycle - (psxNextsCounter - rcnts[i].cycleStart);
-
- if( countToUpdate < 0 )
- {
- psxNextCounter = 0;
- break;
- }
-
- if( countToUpdate < (s32)psxNextCounter )
- {
- psxNextCounter = countToUpdate;
- }
- }
-}
-
-/******************************************************************************/
-
-static
-void psxRcntReset( u32 index )
-{
- u32 count;
-
- if( rcnts[index].counterState == CountToTarget )
- {
- if( rcnts[index].mode & RcCountToTarget )
- {
- count = psxRegs.cycle;
- count -= rcnts[index].cycleStart;
- count /= rcnts[index].rate;
- count -= rcnts[index].target;
- }
- else
- {
- count = _psxRcntRcount( index );
- }
-
- _psxRcntWcount( index, count );
-
- if( rcnts[index].mode & RcIrqOnTarget )
- {
- if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) )
- {
- verboseLog( 3, "[RCNT %i] irq: %x\n", index, count );
- setIrq( rcnts[index].irq );
- rcnts[index].irqState = 1;
- }
- }
-
- rcnts[index].mode |= RcCountEqTarget;
- }
- else if( rcnts[index].counterState == CountToOverflow )
- {
- count = psxRegs.cycle;
- count -= rcnts[index].cycleStart;
- count /= rcnts[index].rate;
- count -= 0xffff;
-
- _psxRcntWcount( index, count );
-
- if( rcnts[index].mode & RcIrqOnOverflow )
- {
- if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) )
- {
- verboseLog( 3, "[RCNT %i] irq: %x\n", index, count );
- setIrq( rcnts[index].irq );
- rcnts[index].irqState = 1;
- }
- }
-
- rcnts[index].mode |= RcOverflow;
- }
-
- rcnts[index].mode |= RcUnknown10;
-
- psxRcntSet();
-}
-
-void psxRcntUpdate()
-{
- u32 cycle;
-
- cycle = psxRegs.cycle;
-
- // rcnt 0.
- if( cycle - rcnts[0].cycleStart >= rcnts[0].cycle )
- {
- psxRcntReset( 0 );
- }
-
- // rcnt 1.
- if( cycle - rcnts[1].cycleStart >= rcnts[1].cycle )
- {
- psxRcntReset( 1 );
- }
-
- // rcnt 2.
- if( cycle - rcnts[2].cycleStart >= rcnts[2].cycle )
- {
- psxRcntReset( 2 );
- }
-
- // rcnt base.
- if( cycle - rcnts[3].cycleStart >= rcnts[3].cycle )
- {
- psxRcntReset( 3 );
-
- GPU_hSync(hSyncCount);
-
- spuSyncCount++;
- hSyncCount++;
-
- // Update spu.
- if( spuSyncCount >= SpuUpdInterval[Config.PsxType] )
- {
- spuSyncCount = 0;
-
- if( SPU_async )
- {
- SPU_async( SpuUpdInterval[Config.PsxType] * rcnts[3].target );
- }
- }
-
- // VSync irq.
- if( hSyncCount == VBlankStart[Config.PsxType] )
- {
- GPU_vBlank( 1 );
-
- // For the best times. :D
- //setIrq( 0x01 );
- }
-
- // Update lace. (with InuYasha fix)
- if( hSyncCount >= (Config.VSyncWA ? HSyncTotal[Config.PsxType] / BIAS : HSyncTotal[Config.PsxType]) )
- {
- hSyncCount = 0;
-
- GPU_vBlank( 0 );
- setIrq( 0x01 );
-
- GPU_updateLace();
- EmuUpdate();
- }
- }
-
- DebugVSync();
-}
-
-/******************************************************************************/
-
-void psxRcntWcount( u32 index, u32 value )
-{
- verboseLog( 2, "[RCNT %i] wcount: %x\n", index, value );
-
- psxRcntUpdate();
-
- _psxRcntWcount( index, value );
- psxRcntSet();
-}
-
-void psxRcntWmode( u32 index, u32 value )
-{
- verboseLog( 1, "[RCNT %i] wmode: %x\n", index, value );
-
- psxRcntUpdate();
-
- rcnts[index].mode = value;
- rcnts[index].irqState = 0;
-
- switch( index )
- {
- case 0:
- if( value & Rc0PixelClock )
- {
- rcnts[index].rate = 5;
- }
- else
- {
- rcnts[index].rate = 1;
- }
- break;
- case 1:
- if( value & Rc1HSyncClock )
- {
- rcnts[index].rate = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType]));
- }
- else
- {
- rcnts[index].rate = 1;
- }
- break;
- case 2:
- if( value & Rc2OneEighthClock )
- {
- rcnts[index].rate = 8;
- }
- else
- {
- rcnts[index].rate = 1;
- }
-
- // TODO: wcount must work.
- if( value & Rc2Disable )
- {
- rcnts[index].rate = 0xffffffff;
- }
- break;
- }
-
- _psxRcntWcount( index, 0 );
- psxRcntSet();
-}
-
-void psxRcntWtarget( u32 index, u32 value )
-{
- verboseLog( 1, "[RCNT %i] wtarget: %x\n", index, value );
-
- psxRcntUpdate();
-
- rcnts[index].target = value;
-
- _psxRcntWcount( index, _psxRcntRcount( index ) );
- psxRcntSet();
-}
-
-/******************************************************************************/
-
-u32 psxRcntRcount( u32 index )
-{
- u32 count;
-
- psxRcntUpdate();
-
- count = _psxRcntRcount( index );
-
- // Parasite Eve 2 fix.
- if( Config.RCntFix )
- {
- if( index == 2 )
- {
- if( rcnts[index].counterState == CountToTarget )
- {
- count /= BIAS;
- }
- }
- }
-
- verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count );
-
- return count;
-}
-
-u32 psxRcntRmode( u32 index )
-{
- u16 mode;
-
- psxRcntUpdate();
-
- mode = rcnts[index].mode;
- rcnts[index].mode &= 0xe7ff;
-
- verboseLog( 2, "[RCNT %i] rmode: %x\n", index, mode );
-
- return mode;
-}
-
-u32 psxRcntRtarget( u32 index )
-{
- verboseLog( 2, "[RCNT %i] rtarget: %x\n", index, rcnts[index].target );
-
- return rcnts[index].target;
-}
-
-/******************************************************************************/
-
-void psxRcntInit()
-{
- s32 i;
-
- // rcnt 0.
- rcnts[0].rate = 1;
- rcnts[0].irq = 0x10;
-
- // rcnt 1.
- rcnts[1].rate = 1;
- rcnts[1].irq = 0x20;
-
- // rcnt 2.
- rcnts[2].rate = 1;
- rcnts[2].irq = 0x40;
-
- // rcnt base.
- rcnts[3].rate = 1;
- rcnts[3].mode = RcCountToTarget;
- rcnts[3].target = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType]));
-
- for( i = 0; i < CounterQuantity; ++i )
- {
- _psxRcntWcount( i, 0 );
- }
-
- hSyncCount = 0;
- spuSyncCount = 0;
-
- psxRcntSet();
-}
-
-/******************************************************************************/
-
-s32 psxRcntFreeze( gzFile f, s32 Mode )
-{
- gzfreeze( &rcnts, sizeof(rcnts) );
- gzfreeze( &hSyncCount, sizeof(hSyncCount) );
- gzfreeze( &spuSyncCount, sizeof(spuSyncCount) );
- gzfreeze( &psxNextCounter, sizeof(psxNextCounter) );
- gzfreeze( &psxNextsCounter, sizeof(psxNextsCounter) );
-
- return 0;
-}
-
-/******************************************************************************/
+/*************************************************************************** + * Copyright (C) 2010 by Blade_Arma * + * * + * 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* + * Internal PSX counters. + */ + +#include "psxcounters.h" + +/******************************************************************************/ + +typedef struct Rcnt +{ + u16 mode, target; + u32 rate, irq, counterState, irqState; + u32 cycle, cycleStart; +} Rcnt; + +enum +{ + Rc0Gate = 0x0001, // 0 not implemented + Rc1Gate = 0x0001, // 0 not implemented + Rc2Disable = 0x0001, // 0 partially implemented + RcUnknown1 = 0x0002, // 1 ? + RcUnknown2 = 0x0004, // 2 ? + RcCountToTarget = 0x0008, // 3 + RcIrqOnTarget = 0x0010, // 4 + RcIrqOnOverflow = 0x0020, // 5 + RcIrqRegenerate = 0x0040, // 6 + RcUnknown7 = 0x0080, // 7 ? + Rc0PixelClock = 0x0100, // 8 fake implementation + Rc1HSyncClock = 0x0100, // 8 + Rc2Unknown8 = 0x0100, // 8 ? + Rc0Unknown9 = 0x0200, // 9 ? + Rc1Unknown9 = 0x0200, // 9 ? + Rc2OneEighthClock = 0x0200, // 9 + RcUnknown10 = 0x0400, // 10 ? + RcCountEqTarget = 0x0800, // 11 + RcOverflow = 0x1000, // 12 + RcUnknown13 = 0x2000, // 13 ? (always zero) + RcUnknown14 = 0x4000, // 14 ? (always zero) + RcUnknown15 = 0x8000, // 15 ? (always zero) +}; + +#define CounterQuantity ( 4 ) +//static const u32 CounterQuantity = 4; + +static const u32 CountToOverflow = 0; +static const u32 CountToTarget = 1; + +static const u32 FrameRate[] = { 60, 50 }; +//static const u32 VBlankStart[] = { 240, 256 }; +static const u32 VBlankStart[] = { 243, 256 }; +static const u32 HSyncTotal[] = { 263, 313 }; +static const u32 SpuUpdInterval[] = { 23, 22 }; + +static const s32 VerboseLevel = 0; + +/******************************************************************************/ + +static Rcnt rcnts[ CounterQuantity ]; + +static u32 hSyncCount = 0; +static u32 spuSyncCount = 0; + +u32 psxNextCounter = 0, psxNextsCounter = 0; + +/******************************************************************************/ + +static inline +void setIrq( u32 irq ) +{ + psxHu32ref(0x1070) |= SWAPu32(irq); +} + +static +void verboseLog( s32 level, const char *str, ... ) +{ + if( level <= VerboseLevel ) + { + va_list va; + char buf[ 4096 ]; + + va_start( va, str ); + vsnprintf( buf, sizeof(buf), str, va ); + va_end( va ); + + printf( "%s", buf ); + fflush( stdout ); + } +} + +/******************************************************************************/ + +static inline +void _psxRcntWcount( u32 index, u32 value ) +{ + if( value > 0xffff ) + { + verboseLog( 1, "[RCNT %i] wcount > 0xffff: %x\n", index, value ); + value &= 0xffff; + } + + rcnts[index].cycleStart = psxRegs.cycle; + rcnts[index].cycleStart -= value * rcnts[index].rate; + + // TODO: <=. + if( value < rcnts[index].target ) + { + rcnts[index].cycle = rcnts[index].target * rcnts[index].rate; + rcnts[index].counterState = CountToTarget; + } + else + { + rcnts[index].cycle = 0xffff * rcnts[index].rate; + rcnts[index].counterState = CountToOverflow; + } +} + +static inline +u32 _psxRcntRcount( u32 index ) +{ + u32 count; + + count = psxRegs.cycle; + count -= rcnts[index].cycleStart; + count /= rcnts[index].rate; + + if( count > 0xffff ) + { + verboseLog( 1, "[RCNT %i] rcount > 0xffff: %x\n", index, count ); + count &= 0xffff; + } + + return count; +} + +/******************************************************************************/ + +static +void psxRcntSet() +{ + s32 countToUpdate; + u32 i; + + psxNextsCounter = psxRegs.cycle; + psxNextCounter = 0x7fffffff; + + for( i = 0; i < CounterQuantity; ++i ) + { + countToUpdate = rcnts[i].cycle - (psxNextsCounter - rcnts[i].cycleStart); + + if( countToUpdate < 0 ) + { + psxNextCounter = 0; + break; + } + + if( countToUpdate < (s32)psxNextCounter ) + { + psxNextCounter = countToUpdate; + } + } +} + +/******************************************************************************/ + +static +void psxRcntReset( u32 index ) +{ + u32 count; + + if( rcnts[index].counterState == CountToTarget ) + { + if( rcnts[index].mode & RcCountToTarget ) + { + count = psxRegs.cycle; + count -= rcnts[index].cycleStart; + count /= rcnts[index].rate; + count -= rcnts[index].target; + } + else + { + count = _psxRcntRcount( index ); + } + + _psxRcntWcount( index, count ); + + if( rcnts[index].mode & RcIrqOnTarget ) + { + if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) ) + { + verboseLog( 3, "[RCNT %i] irq: %x\n", index, count ); + setIrq( rcnts[index].irq ); + rcnts[index].irqState = 1; + } + } + + rcnts[index].mode |= RcCountEqTarget; + } + else if( rcnts[index].counterState == CountToOverflow ) + { + count = psxRegs.cycle; + count -= rcnts[index].cycleStart; + count /= rcnts[index].rate; + count -= 0xffff; + + _psxRcntWcount( index, count ); + + if( rcnts[index].mode & RcIrqOnOverflow ) + { + if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) ) + { + verboseLog( 3, "[RCNT %i] irq: %x\n", index, count ); + setIrq( rcnts[index].irq ); + rcnts[index].irqState = 1; + } + } + + rcnts[index].mode |= RcOverflow; + } + + rcnts[index].mode |= RcUnknown10; + + psxRcntSet(); +} + +void psxRcntUpdate() +{ + u32 cycle; + + cycle = psxRegs.cycle; + + // rcnt 0. + if( cycle - rcnts[0].cycleStart >= rcnts[0].cycle ) + { + psxRcntReset( 0 ); + } + + // rcnt 1. + if( cycle - rcnts[1].cycleStart >= rcnts[1].cycle ) + { + psxRcntReset( 1 ); + } + + // rcnt 2. + if( cycle - rcnts[2].cycleStart >= rcnts[2].cycle ) + { + psxRcntReset( 2 ); + } + + // rcnt base. + if( cycle - rcnts[3].cycleStart >= rcnts[3].cycle ) + { + psxRcntReset( 3 ); + + GPU_hSync(hSyncCount); + + spuSyncCount++; + hSyncCount++; + + // Update spu. + if( spuSyncCount >= SpuUpdInterval[Config.PsxType] ) + { + spuSyncCount = 0; + + if( SPU_async ) + { + SPU_async( SpuUpdInterval[Config.PsxType] * rcnts[3].target ); + } + } + + // VSync irq. + if( hSyncCount == VBlankStart[Config.PsxType] ) + { + GPU_vBlank( 1 ); + + // For the best times. :D + //setIrq( 0x01 ); + } + + // Update lace. (with InuYasha fix) + if( hSyncCount >= (Config.VSyncWA ? HSyncTotal[Config.PsxType] / BIAS : HSyncTotal[Config.PsxType]) ) + { + hSyncCount = 0; + + GPU_vBlank( 0 ); + setIrq( 0x01 ); + + GPU_updateLace(); + EmuUpdate(); + } + } + + DebugVSync(); +} + +/******************************************************************************/ + +void psxRcntWcount( u32 index, u32 value ) +{ + verboseLog( 2, "[RCNT %i] wcount: %x\n", index, value ); + + psxRcntUpdate(); + + _psxRcntWcount( index, value ); + psxRcntSet(); +} + +void psxRcntWmode( u32 index, u32 value ) +{ + verboseLog( 1, "[RCNT %i] wmode: %x\n", index, value ); + + psxRcntUpdate(); + + rcnts[index].mode = value; + rcnts[index].irqState = 0; + + switch( index ) + { + case 0: + if( value & Rc0PixelClock ) + { + rcnts[index].rate = 5; + } + else + { + rcnts[index].rate = 1; + } + break; + case 1: + if( value & Rc1HSyncClock ) + { + rcnts[index].rate = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType])); + } + else + { + rcnts[index].rate = 1; + } + break; + case 2: + if( value & Rc2OneEighthClock ) + { + rcnts[index].rate = 8; + } + else + { + rcnts[index].rate = 1; + } + + // TODO: wcount must work. + if( value & Rc2Disable ) + { + rcnts[index].rate = 0xffffffff; + } + break; + } + + _psxRcntWcount( index, 0 ); + psxRcntSet(); +} + +void psxRcntWtarget( u32 index, u32 value ) +{ + verboseLog( 1, "[RCNT %i] wtarget: %x\n", index, value ); + + psxRcntUpdate(); + + rcnts[index].target = value; + + _psxRcntWcount( index, _psxRcntRcount( index ) ); + psxRcntSet(); +} + +/******************************************************************************/ + +u32 psxRcntRcount( u32 index ) +{ + u32 count; + + psxRcntUpdate(); + + count = _psxRcntRcount( index ); + + // Parasite Eve 2 fix. + if( Config.RCntFix ) + { + if( index == 2 ) + { + if( rcnts[index].counterState == CountToTarget ) + { + count /= BIAS; + } + } + } + + verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count ); + + return count; +} + +u32 psxRcntRmode( u32 index ) +{ + u16 mode; + + psxRcntUpdate(); + + mode = rcnts[index].mode; + rcnts[index].mode &= 0xe7ff; + + verboseLog( 2, "[RCNT %i] rmode: %x\n", index, mode ); + + return mode; +} + +u32 psxRcntRtarget( u32 index ) +{ + verboseLog( 2, "[RCNT %i] rtarget: %x\n", index, rcnts[index].target ); + + return rcnts[index].target; +} + +/******************************************************************************/ + +void psxRcntInit() +{ + s32 i; + + // rcnt 0. + rcnts[0].rate = 1; + rcnts[0].irq = 0x10; + + // rcnt 1. + rcnts[1].rate = 1; + rcnts[1].irq = 0x20; + + // rcnt 2. + rcnts[2].rate = 1; + rcnts[2].irq = 0x40; + + // rcnt base. + rcnts[3].rate = 1; + rcnts[3].mode = RcCountToTarget; + rcnts[3].target = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType])); + + for( i = 0; i < CounterQuantity; ++i ) + { + _psxRcntWcount( i, 0 ); + } + + hSyncCount = 0; + spuSyncCount = 0; + + psxRcntSet(); +} + +/******************************************************************************/ + +s32 psxRcntFreeze( gzFile f, s32 Mode ) +{ + gzfreeze( &rcnts, sizeof(rcnts) ); + gzfreeze( &hSyncCount, sizeof(hSyncCount) ); + gzfreeze( &spuSyncCount, sizeof(spuSyncCount) ); + gzfreeze( &psxNextCounter, sizeof(psxNextCounter) ); + gzfreeze( &psxNextsCounter, sizeof(psxNextsCounter) ); + + return 0; +} + +/******************************************************************************/ diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 6b0d3e4c..eaa30004 100644..100755 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -1,1111 +1,1111 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
- * PSX assembly interpreter.
- */
-
-#include "psxcommon.h"
-#include "r3000a.h"
-#include "gte.h"
-#include "psxhle.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() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
-#else
-#define debugI()
-#endif
-
-static inline void execI();
-
-// Subsets
-void (*psxBSC[64])();
-void (*psxSPC[64])();
-void (*psxREG[32])();
-void (*psxCP0[32])();
-void (*psxCP2[64])();
-void (*psxCP2BSC[32])();
-
-static void delayRead(int reg, u32 bpc) {
- u32 rold, rnew;
-
-// SysPrintf("delayRead at %x!\n", psxRegs.pc);
-
- rold = psxRegs.GPR.r[reg];
- psxBSC[psxRegs.code >> 26](); // branch delay load
- rnew = psxRegs.GPR.r[reg];
-
- psxRegs.pc = bpc;
-
- branch = 0;
-
- psxRegs.GPR.r[reg] = rold;
- execI(); // first branch opcode
- psxRegs.GPR.r[reg] = rnew;
-
- psxBranchTest();
-}
-
-static void delayWrite(int reg, u32 bpc) {
-
-/* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
-
- SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
- SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
-
- // no changes from normal behavior
-
- psxBSC[psxRegs.code >> 26]();
-
- branch = 0;
- psxRegs.pc = bpc;
-
- psxBranchTest();
-}
-
-static void delayReadWrite(int reg, u32 bpc) {
-
-// SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
-
- // the branch delay load is skipped
-
- branch = 0;
- psxRegs.pc = bpc;
-
- psxBranchTest();
-}
-
-// this defines shall be used with the tmp
-// of the next func (instead of _Funct_...)
-#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
-#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
-#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
-#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
-#define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
-
-int psxTestLoadDelay(int reg, u32 tmp) {
- if (tmp == 0) return 0; // NOP
- switch (tmp >> 26) {
- case 0x00: // SPECIAL
- switch (_tFunct_) {
- case 0x00: // SLL
- case 0x02: case 0x03: // SRL/SRA
- if (_tRd_ == reg && _tRt_ == reg) return 1; else
- if (_tRt_ == reg) return 2; else
- if (_tRd_ == reg) return 3;
- break;
-
- case 0x08: // JR
- if (_tRs_ == reg) return 2;
- break;
- case 0x09: // JALR
- if (_tRd_ == reg && _tRs_ == reg) return 1; else
- if (_tRs_ == reg) return 2; else
- if (_tRd_ == reg) return 3;
- break;
-
- // SYSCALL/BREAK just a break;
-
- case 0x20: case 0x21: case 0x22: case 0x23:
- case 0x24: case 0x25: case 0x26: case 0x27:
- case 0x2a: case 0x2b: // ADD/ADDU...
- case 0x04: case 0x06: case 0x07: // SLLV...
- if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
- if (_tRt_ == reg || _tRs_ == reg) return 2; else
- if (_tRd_ == reg) return 3;
- break;
-
- case 0x10: case 0x12: // MFHI/MFLO
- if (_tRd_ == reg) return 3;
- break;
- case 0x11: case 0x13: // MTHI/MTLO
- if (_tRs_ == reg) return 2;
- break;
-
- case 0x18: case 0x19:
- case 0x1a: case 0x1b: // MULT/DIV...
- if (_tRt_ == reg || _tRs_ == reg) return 2;
- break;
- }
- break;
-
- case 0x01: // REGIMM
- switch (_tRt_) {
- case 0x00: case 0x01:
- case 0x10: case 0x11: // BLTZ/BGEZ...
- // Xenogears - lbu v0 / beq v0
- // - no load delay (fixes battle loading)
- break;
-
- if (_tRs_ == reg) return 2;
- break;
- }
- break;
-
- // J would be just a break;
- case 0x03: // JAL
- if (31 == reg) return 3;
- break;
-
- case 0x04: case 0x05: // BEQ/BNE
- // Xenogears - lbu v0 / beq v0
- // - no load delay (fixes battle loading)
- break;
-
- if (_tRs_ == reg || _tRt_ == reg) return 2;
- break;
-
- case 0x06: case 0x07: // BLEZ/BGTZ
- // Xenogears - lbu v0 / beq v0
- // - no load delay (fixes battle loading)
- break;
-
- if (_tRs_ == reg) return 2;
- break;
-
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
- if (_tRt_ == reg && _tRs_ == reg) return 1; else
- if (_tRs_ == reg) return 2; else
- if (_tRt_ == reg) return 3;
- break;
-
- case 0x0f: // LUI
- if (_tRt_ == reg) return 3;
- break;
-
- case 0x10: // COP0
- switch (_tFunct_) {
- case 0x00: // MFC0
- if (_tRt_ == reg) return 3;
- break;
- case 0x02: // CFC0
- if (_tRt_ == reg) return 3;
- break;
- case 0x04: // MTC0
- if (_tRt_ == reg) return 2;
- break;
- case 0x06: // CTC0
- if (_tRt_ == reg) return 2;
- break;
- // RFE just a break;
- }
- break;
-
- case 0x12: // COP2
- switch (_tFunct_) {
- case 0x00:
- switch (_tRs_) {
- case 0x00: // MFC2
- if (_tRt_ == reg) return 3;
- break;
- case 0x02: // CFC2
- if (_tRt_ == reg) return 3;
- break;
- case 0x04: // MTC2
- if (_tRt_ == reg) return 2;
- break;
- case 0x06: // CTC2
- if (_tRt_ == reg) return 2;
- break;
- }
- break;
- // RTPS... break;
- }
- break;
-
- case 0x22: case 0x26: // LWL/LWR
- if (_tRt_ == reg) return 3; else
- if (_tRs_ == reg) return 2;
- break;
-
- case 0x20: case 0x21: case 0x23:
- case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
- if (_tRt_ == reg && _tRs_ == reg) return 1; else
- if (_tRs_ == reg) return 2; else
- if (_tRt_ == reg) return 3;
- break;
-
- case 0x28: case 0x29: case 0x2a:
- case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
- if (_tRt_ == reg || _tRs_ == reg) return 2;
- break;
-
- case 0x32: case 0x3a: // LWC2/SWC2
- if (_tRs_ == reg) return 2;
- break;
- }
-
- return 0;
-}
-
-void psxDelayTest(int reg, u32 bpc) {
- u32 *code;
- u32 tmp;
-
- // Don't execute yet - just peek
- code = Read_ICache(bpc, TRUE);
-
- tmp = ((code == NULL) ? 0 : SWAP32(*code));
- branch = 1;
-
- switch (psxTestLoadDelay(reg, tmp)) {
- case 1:
- delayReadWrite(reg, bpc); return;
- case 2:
- delayRead(reg, bpc); return;
- case 3:
- delayWrite(reg, bpc); return;
- }
- psxBSC[psxRegs.code >> 26]();
-
- branch = 0;
- psxRegs.pc = bpc;
-
- psxBranchTest();
-}
-
-static u32 psxBranchNoDelay(void) {
- u32 *code;
- u32 temp;
-
- code = Read_ICache(psxRegs.pc, TRUE);
- psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
- switch (_Op_) {
- case 0x00: // SPECIAL
- switch (_Funct_) {
- case 0x08: // JR
- return _u32(_rRs_);
- case 0x09: // JALR
- temp = _u32(_rRs_);
- if (_Rd_) { _SetLink(_Rd_); }
- return temp;
- }
- break;
- case 0x01: // REGIMM
- switch (_Rt_) {
- case 0x00: // BLTZ
- if (_i32(_rRs_) < 0)
- return _BranchTarget_;
- break;
- case 0x01: // BGEZ
- if (_i32(_rRs_) >= 0)
- return _BranchTarget_;
- break;
- case 0x08: // BLTZAL
- if (_i32(_rRs_) < 0) {
- _SetLink(31);
- return _BranchTarget_;
- }
- break;
- case 0x09: // BGEZAL
- if (_i32(_rRs_) >= 0) {
- _SetLink(31);
- return _BranchTarget_;
- }
- break;
- }
- break;
- case 0x02: // J
- return _JumpTarget_;
- case 0x03: // JAL
- _SetLink(31);
- return _JumpTarget_;
- case 0x04: // BEQ
- if (_i32(_rRs_) == _i32(_rRt_))
- return _BranchTarget_;
- break;
- case 0x05: // BNE
- if (_i32(_rRs_) != _i32(_rRt_))
- return _BranchTarget_;
- break;
- case 0x06: // BLEZ
- if (_i32(_rRs_) <= 0)
- return _BranchTarget_;
- break;
- case 0x07: // BGTZ
- if (_i32(_rRs_) > 0)
- return _BranchTarget_;
- break;
- }
-
- return (u32)-1;
-}
-
-static int psxDelayBranchExec(u32 tar) {
- execI();
-
- branch = 0;
- psxRegs.pc = tar;
- psxRegs.cycle += BIAS;
- psxBranchTest();
- return 1;
-}
-
-static int psxDelayBranchTest(u32 tar1) {
- u32 tar2, tmp1, tmp2;
-
- tar2 = psxBranchNoDelay();
- if (tar2 == (u32)-1)
- return 0;
-
- debugI();
-
- /*
- * Branch in delay slot:
- * - execute 1 instruction at tar1
- * - jump to tar2 (target of branch in delay slot; this branch
- * has no normal delay slot, instruction at tar1 was fetched instead)
- */
- psxRegs.pc = tar1;
- tmp1 = psxBranchNoDelay();
- if (tmp1 == (u32)-1) {
- return psxDelayBranchExec(tar2);
- }
- debugI();
- psxRegs.cycle += BIAS;
-
- /*
- * Got a branch at tar1:
- * - execute 1 instruction at tar2
- * - jump to target of that branch (tmp1)
- */
- psxRegs.pc = tar2;
- tmp2 = psxBranchNoDelay();
- if (tmp2 == (u32)-1) {
- return psxDelayBranchExec(tmp1);
- }
- debugI();
- psxRegs.cycle += BIAS;
-
- /*
- * Got a branch at tar2:
- * - execute 1 instruction at tmp1
- * - jump to target of that branch (tmp2)
- */
- psxRegs.pc = tmp1;
- return psxDelayBranchExec(tmp2);
-}
-
-static __inline void doBranch(u32 tar) {
- u32 *code;
- u32 tmp;
-
- branch2 = branch = 1;
- branchPC = tar;
-
- // notaz: check for branch in delay slot
- if (psxDelayBranchTest(tar))
- return;
-
- // branch delay slot
- code = Read_ICache(psxRegs.pc, TRUE);
-
- psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
-
- debugI();
-
- psxRegs.pc += 4;
- psxRegs.cycle += BIAS;
-
- // check for load delay
- tmp = psxRegs.code >> 26;
- switch (tmp) {
- case 0x10: // COP0
- switch (_Rs_) {
- case 0x00: // MFC0
- case 0x02: // CFC0
- psxDelayTest(_Rt_, branchPC);
- return;
- }
- break;
- case 0x12: // COP2
- switch (_Funct_) {
- case 0x00:
- switch (_Rs_) {
- case 0x00: // MFC2
- case 0x02: // CFC2
- psxDelayTest(_Rt_, branchPC);
- return;
- }
- break;
- }
- break;
- case 0x32: // LWC2
- psxDelayTest(_Rt_, branchPC);
- return;
- default:
- if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
- psxDelayTest(_Rt_, branchPC);
- return;
- }
- break;
- }
-
- psxBSC[psxRegs.code >> 26]();
-
- branch = 0;
- psxRegs.pc = branchPC;
-
- psxBranchTest();
-}
-
-/*********************************************************
-* 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_) 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_) < ((u32)_Imm_); } // 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 (_i32(_rRt_) != 0) {
- _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
- _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
- }
- else {
- _i32(_rLo_) = 0xffffffff;
- _i32(_rHi_) = _i32(_rRs_);
- }
-}
-
-void psxDIVU() {
- if (_rRt_ != 0) {
- _rLo_ = _rRs_ / _rRt_;
- _rHi_ = _rRs_ % _rRt_;
- }
- else {
- _rLo_ = 0xffffffff;
- _rHi_ = _rRs_;
- }
-}
-
-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; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
-void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
-void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
-
-/*********************************************************
-* Shift arithmetic with variant register shift *
-* Format: OP rd, rt, rs *
-*********************************************************/
-void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
-void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
-void psxSRLV() { if (!_Rd_) return; _u32(_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; _u32(_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
-}
-
-void psxSYSCALL() {
- psxRegs.pc -= 4;
- psxException(0x20, branch);
-}
-
-void psxRFE() {
-// SysPrintf("psxRFE\n");
- psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
- ((psxRegs.CP0.n.Status & 0x3c) >> 2);
-}
-
-/*********************************************************
-* 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_); }
-
-/*********************************************************
-* Register jump *
-* Format: OP rs, rd *
-*********************************************************/
-void psxJR() {
- doBranch(_u32(_rRs_));
- psxJumpTest();
-}
-
-void psxJALR() {
- u32 temp = _u32(_rRs_);
- if (_Rd_) { _SetLink(_Rd_); }
- doBranch(temp);
-}
-
-/*********************************************************
-* Load and store for GPR *
-* Format: OP rt, offset(base) *
-*********************************************************/
-
-#define _oB_ (_u32(_rRs_) + _Imm_)
-
-void psxLB() {
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
-
- if (_Rt_) {
- _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
- } else {
- psxMemRead8(_oB_);
- }
-}
-
-void psxLBU() {
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
-
- if (_Rt_) {
- _u32(_rRt_) = psxMemRead8(_oB_);
- } else {
- psxMemRead8(_oB_);
- }
-}
-
-void psxLH() {
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
-
- if (_Rt_) {
- _i32(_rRt_) = (short)psxMemRead16(_oB_);
- } else {
- psxMemRead16(_oB_);
- }
-}
-
-void psxLHU() {
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
-
- if (_Rt_) {
- _u32(_rRt_) = psxMemRead16(_oB_);
- } else {
- psxMemRead16(_oB_);
- }
-}
-
-void psxLW() {
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
-
- if (_Rt_) {
- _u32(_rRt_) = psxMemRead32(_oB_);
- } else {
- psxMemRead32(_oB_);
- }
-}
-
-u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
-u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
-
-void psxLWL() {
- u32 addr = _oB_;
- u32 shift = addr & 3;
- u32 mem = psxMemRead32(addr & ~3);
-
-
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
- if (!_Rt_) return;
- _u32(_rRt_) = ( _u32(_rRt_) & 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 psxLWR() {
- u32 addr = _oB_;
- u32 shift = addr & 3;
- u32 mem = psxMemRead32(addr & ~3);
-
-
-
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
-
- if (!_Rt_) return;
- _u32(_rRt_) = ( _u32(_rRt_) & 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 psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
-void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
-void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
-
-u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
-u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
-
-void psxSWL() {
- u32 addr = _oB_;
- u32 shift = addr & 3;
- u32 mem = psxMemRead32(addr & ~3);
-
- psxMemWrite32(addr & ~3, (_u32(_rRt_) >> 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] = { 0, 0xff, 0xffff, 0xffffff };
-u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
-
-void psxSWR() {
- u32 addr = _oB_;
- u32 shift = addr & 3;
- u32 mem = psxMemRead32(addr & ~3);
-
- psxMemWrite32(addr & ~3, (_u32(_rRt_) << 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)
- */
-}
-
-/*********************************************************
-* Moves between GPR and COPx *
-* Format: OP rt, fs *
-*********************************************************/
-void psxMFC0()
-{
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
- if (!_Rt_) return;
-
- _i32(_rRt_) = (int)_rFs_;
-}
-
-void psxCFC0()
-{
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
-
- if (!_Rt_) return;
-
- _i32(_rRt_) = (int)_rFs_;
-}
-
-void psxTestSWInts() {
- // the next code is untested, if u know please
- // tell me if it works ok or not (linuzappz)
- if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
- psxRegs.CP0.n.Status & 0x1) {
- psxException(psxRegs.CP0.n.Cause, branch);
- }
-}
-
-static __inline void MTC0(int reg, u32 val) {
-// SysPrintf("MTC0 %d: %x\n", reg, val);
- switch (reg) {
- case 12: // Status
- psxRegs.CP0.r[12] = val;
- psxTestSWInts();
- break;
-
- case 13: // Cause
- psxRegs.CP0.n.Cause = val & ~(0xfc00);
- psxTestSWInts();
- break;
-
- default:
- psxRegs.CP0.r[reg] = val;
- break;
- }
-}
-
-void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
-void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
-
-
-
-void psxMFC2()
-{
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
- gteMFC2();
-}
-
-
-void psxCFC2()
-{
- // load delay = 1 latency
- if( branch == 0 )
- {
- // simulate: beq r0,r0,lw+4 / lw / (delay slot)
- psxRegs.pc -= 4;
- doBranch( psxRegs.pc + 4 );
-
- return;
- }
-
- gteCFC2();
-}
-
-
-/*********************************************************
-* Unknow instruction (would generate an exception) *
-* Format: ? *
-*********************************************************/
-void psxNULL() {
-#ifdef PSXCPU_LOG
- PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
-#endif
-}
-
-void psxSPECIAL() {
- psxSPC[_Funct_]();
-}
-
-void psxREGIMM() {
- psxREG[_Rt_]();
-}
-
-void psxCOP0() {
- psxCP0[_Rs_]();
-}
-
-void psxCOP2() {
- if ((psxRegs.CP0.n.Status & 0x40000000) == 0 )
- return;
-
- psxCP2[_Funct_]();
-}
-
-void psxBASIC() {
- psxCP2BSC[_Rs_]();
-}
-
-void psxHLE() {
-// psxHLEt[psxRegs.code & 0xffff]();
- psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
-}
-
-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 , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
- psxNULL , psxNULL , gteSWC2, psxHLE , 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, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
- psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
- gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
- psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
- gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
- gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
- gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
- psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
-};
-
-void (*psxCP2BSC[32])() = {
- psxMFC2, psxNULL, psxCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, 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() {
- psxRegs.ICache_valid = FALSE;
-}
-
-static void intExecute() {
- for (;;)
- execI();
-}
-
-static void intExecuteBlock() {
- branch2 = 0;
- while (!branch2) execI();
-}
-
-static void intClear(u32 Addr, u32 Size) {
-}
-
-static void intShutdown() {
-}
-
-// interpreter execution
-static inline void execI() {
- u32 *code = Read_ICache(psxRegs.pc, FALSE);
- psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
-
- debugI();
-
- if (Config.Debug) ProcessDebug();
-
- psxRegs.pc += 4;
- psxRegs.cycle += BIAS;
-
- psxBSC[psxRegs.code >> 26]();
-}
-
-R3000Acpu psxInt = {
- intInit,
- intReset,
- intExecute,
- intExecuteBlock,
- intClear,
- intShutdown
-};
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* + * PSX assembly interpreter. + */ + +#include "psxcommon.h" +#include "r3000a.h" +#include "gte.h" +#include "psxhle.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() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); +#else +#define debugI() +#endif + +static inline void execI(); + +// Subsets +void (*psxBSC[64])(); +void (*psxSPC[64])(); +void (*psxREG[32])(); +void (*psxCP0[32])(); +void (*psxCP2[64])(); +void (*psxCP2BSC[32])(); + +static void delayRead(int reg, u32 bpc) { + u32 rold, rnew; + +// SysPrintf("delayRead at %x!\n", psxRegs.pc); + + rold = psxRegs.GPR.r[reg]; + psxBSC[psxRegs.code >> 26](); // branch delay load + rnew = psxRegs.GPR.r[reg]; + + psxRegs.pc = bpc; + + branch = 0; + + psxRegs.GPR.r[reg] = rold; + execI(); // first branch opcode + psxRegs.GPR.r[reg] = rnew; + + psxBranchTest(); +} + +static void delayWrite(int reg, u32 bpc) { + +/* SysPrintf("delayWrite at %x!\n", psxRegs.pc); + + SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4)); + SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/ + + // no changes from normal behavior + + psxBSC[psxRegs.code >> 26](); + + branch = 0; + psxRegs.pc = bpc; + + psxBranchTest(); +} + +static void delayReadWrite(int reg, u32 bpc) { + +// SysPrintf("delayReadWrite at %x!\n", psxRegs.pc); + + // the branch delay load is skipped + + branch = 0; + psxRegs.pc = bpc; + + psxBranchTest(); +} + +// this defines shall be used with the tmp +// of the next func (instead of _Funct_...) +#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register +#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register +#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register +#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register +#define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register + +int psxTestLoadDelay(int reg, u32 tmp) { + if (tmp == 0) return 0; // NOP + switch (tmp >> 26) { + case 0x00: // SPECIAL + switch (_tFunct_) { + case 0x00: // SLL + case 0x02: case 0x03: // SRL/SRA + if (_tRd_ == reg && _tRt_ == reg) return 1; else + if (_tRt_ == reg) return 2; else + if (_tRd_ == reg) return 3; + break; + + case 0x08: // JR + if (_tRs_ == reg) return 2; + break; + case 0x09: // JALR + if (_tRd_ == reg && _tRs_ == reg) return 1; else + if (_tRs_ == reg) return 2; else + if (_tRd_ == reg) return 3; + break; + + // SYSCALL/BREAK just a break; + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x2a: case 0x2b: // ADD/ADDU... + case 0x04: case 0x06: case 0x07: // SLLV... + if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else + if (_tRt_ == reg || _tRs_ == reg) return 2; else + if (_tRd_ == reg) return 3; + break; + + case 0x10: case 0x12: // MFHI/MFLO + if (_tRd_ == reg) return 3; + break; + case 0x11: case 0x13: // MTHI/MTLO + if (_tRs_ == reg) return 2; + break; + + case 0x18: case 0x19: + case 0x1a: case 0x1b: // MULT/DIV... + if (_tRt_ == reg || _tRs_ == reg) return 2; + break; + } + break; + + case 0x01: // REGIMM + switch (_tRt_) { + case 0x00: case 0x01: + case 0x10: case 0x11: // BLTZ/BGEZ... + // Xenogears - lbu v0 / beq v0 + // - no load delay (fixes battle loading) + break; + + if (_tRs_ == reg) return 2; + break; + } + break; + + // J would be just a break; + case 0x03: // JAL + if (31 == reg) return 3; + break; + + case 0x04: case 0x05: // BEQ/BNE + // Xenogears - lbu v0 / beq v0 + // - no load delay (fixes battle loading) + break; + + if (_tRs_ == reg || _tRt_ == reg) return 2; + break; + + case 0x06: case 0x07: // BLEZ/BGTZ + // Xenogears - lbu v0 / beq v0 + // - no load delay (fixes battle loading) + break; + + if (_tRs_ == reg) return 2; + break; + + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU... + if (_tRt_ == reg && _tRs_ == reg) return 1; else + if (_tRs_ == reg) return 2; else + if (_tRt_ == reg) return 3; + break; + + case 0x0f: // LUI + if (_tRt_ == reg) return 3; + break; + + case 0x10: // COP0 + switch (_tFunct_) { + case 0x00: // MFC0 + if (_tRt_ == reg) return 3; + break; + case 0x02: // CFC0 + if (_tRt_ == reg) return 3; + break; + case 0x04: // MTC0 + if (_tRt_ == reg) return 2; + break; + case 0x06: // CTC0 + if (_tRt_ == reg) return 2; + break; + // RFE just a break; + } + break; + + case 0x12: // COP2 + switch (_tFunct_) { + case 0x00: + switch (_tRs_) { + case 0x00: // MFC2 + if (_tRt_ == reg) return 3; + break; + case 0x02: // CFC2 + if (_tRt_ == reg) return 3; + break; + case 0x04: // MTC2 + if (_tRt_ == reg) return 2; + break; + case 0x06: // CTC2 + if (_tRt_ == reg) return 2; + break; + } + break; + // RTPS... break; + } + break; + + case 0x22: case 0x26: // LWL/LWR + if (_tRt_ == reg) return 3; else + if (_tRs_ == reg) return 2; + break; + + case 0x20: case 0x21: case 0x23: + case 0x24: case 0x25: // LB/LH/LW/LBU/LHU + if (_tRt_ == reg && _tRs_ == reg) return 1; else + if (_tRs_ == reg) return 2; else + if (_tRt_ == reg) return 3; + break; + + case 0x28: case 0x29: case 0x2a: + case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR + if (_tRt_ == reg || _tRs_ == reg) return 2; + break; + + case 0x32: case 0x3a: // LWC2/SWC2 + if (_tRs_ == reg) return 2; + break; + } + + return 0; +} + +void psxDelayTest(int reg, u32 bpc) { + u32 *code; + u32 tmp; + + // Don't execute yet - just peek + code = Read_ICache(bpc, TRUE); + + tmp = ((code == NULL) ? 0 : SWAP32(*code)); + branch = 1; + + switch (psxTestLoadDelay(reg, tmp)) { + case 1: + delayReadWrite(reg, bpc); return; + case 2: + delayRead(reg, bpc); return; + case 3: + delayWrite(reg, bpc); return; + } + psxBSC[psxRegs.code >> 26](); + + branch = 0; + psxRegs.pc = bpc; + + psxBranchTest(); +} + +static u32 psxBranchNoDelay(void) { + u32 *code; + u32 temp; + + code = Read_ICache(psxRegs.pc, TRUE); + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + switch (_Op_) { + case 0x00: // SPECIAL + switch (_Funct_) { + case 0x08: // JR + return _u32(_rRs_); + case 0x09: // JALR + temp = _u32(_rRs_); + if (_Rd_) { _SetLink(_Rd_); } + return temp; + } + break; + case 0x01: // REGIMM + switch (_Rt_) { + case 0x00: // BLTZ + if (_i32(_rRs_) < 0) + return _BranchTarget_; + break; + case 0x01: // BGEZ + if (_i32(_rRs_) >= 0) + return _BranchTarget_; + break; + case 0x08: // BLTZAL + if (_i32(_rRs_) < 0) { + _SetLink(31); + return _BranchTarget_; + } + break; + case 0x09: // BGEZAL + if (_i32(_rRs_) >= 0) { + _SetLink(31); + return _BranchTarget_; + } + break; + } + break; + case 0x02: // J + return _JumpTarget_; + case 0x03: // JAL + _SetLink(31); + return _JumpTarget_; + case 0x04: // BEQ + if (_i32(_rRs_) == _i32(_rRt_)) + return _BranchTarget_; + break; + case 0x05: // BNE + if (_i32(_rRs_) != _i32(_rRt_)) + return _BranchTarget_; + break; + case 0x06: // BLEZ + if (_i32(_rRs_) <= 0) + return _BranchTarget_; + break; + case 0x07: // BGTZ + if (_i32(_rRs_) > 0) + return _BranchTarget_; + break; + } + + return (u32)-1; +} + +static int psxDelayBranchExec(u32 tar) { + execI(); + + branch = 0; + psxRegs.pc = tar; + psxRegs.cycle += BIAS; + psxBranchTest(); + return 1; +} + +static int psxDelayBranchTest(u32 tar1) { + u32 tar2, tmp1, tmp2; + + tar2 = psxBranchNoDelay(); + if (tar2 == (u32)-1) + return 0; + + debugI(); + + /* + * Branch in delay slot: + * - execute 1 instruction at tar1 + * - jump to tar2 (target of branch in delay slot; this branch + * has no normal delay slot, instruction at tar1 was fetched instead) + */ + psxRegs.pc = tar1; + tmp1 = psxBranchNoDelay(); + if (tmp1 == (u32)-1) { + return psxDelayBranchExec(tar2); + } + debugI(); + psxRegs.cycle += BIAS; + + /* + * Got a branch at tar1: + * - execute 1 instruction at tar2 + * - jump to target of that branch (tmp1) + */ + psxRegs.pc = tar2; + tmp2 = psxBranchNoDelay(); + if (tmp2 == (u32)-1) { + return psxDelayBranchExec(tmp1); + } + debugI(); + psxRegs.cycle += BIAS; + + /* + * Got a branch at tar2: + * - execute 1 instruction at tmp1 + * - jump to target of that branch (tmp2) + */ + psxRegs.pc = tmp1; + return psxDelayBranchExec(tmp2); +} + +static __inline void doBranch(u32 tar) { + u32 *code; + u32 tmp; + + branch2 = branch = 1; + branchPC = tar; + + // notaz: check for branch in delay slot + if (psxDelayBranchTest(tar)) + return; + + // branch delay slot + code = Read_ICache(psxRegs.pc, TRUE); + + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + + debugI(); + + psxRegs.pc += 4; + psxRegs.cycle += BIAS; + + // check for load delay + tmp = psxRegs.code >> 26; + switch (tmp) { + case 0x10: // COP0 + switch (_Rs_) { + case 0x00: // MFC0 + case 0x02: // CFC0 + psxDelayTest(_Rt_, branchPC); + return; + } + break; + case 0x12: // COP2 + switch (_Funct_) { + case 0x00: + switch (_Rs_) { + case 0x00: // MFC2 + case 0x02: // CFC2 + psxDelayTest(_Rt_, branchPC); + return; + } + break; + } + break; + case 0x32: // LWC2 + psxDelayTest(_Rt_, branchPC); + return; + default: + if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR + psxDelayTest(_Rt_, branchPC); + return; + } + break; + } + + psxBSC[psxRegs.code >> 26](); + + branch = 0; + psxRegs.pc = branchPC; + + psxBranchTest(); +} + +/********************************************************* +* 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_) 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_) < ((u32)_Imm_); } // 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 (_i32(_rRt_) != 0) { + _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_); + _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_); + } + else { + _i32(_rLo_) = 0xffffffff; + _i32(_rHi_) = _i32(_rRs_); + } +} + +void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } + else { + _rLo_ = 0xffffffff; + _rHi_ = _rRs_; + } +} + +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; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa +void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic) +void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs +void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) +void psxSRLV() { if (!_Rd_) return; _u32(_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; _u32(_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 +} + +void psxSYSCALL() { + psxRegs.pc -= 4; + psxException(0x20, branch); +} + +void psxRFE() { +// SysPrintf("psxRFE\n"); + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +} + +/********************************************************* +* 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_); } + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void psxJR() { + doBranch(_u32(_rRs_)); + psxJumpTest(); +} + +void psxJALR() { + u32 temp = _u32(_rRs_); + if (_Rd_) { _SetLink(_Rd_); } + doBranch(temp); +} + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +#define _oB_ (_u32(_rRs_) + _Imm_) + +void psxLB() { + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + + if (_Rt_) { + _i32(_rRt_) = (signed char)psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLBU() { + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + + if (_Rt_) { + _u32(_rRt_) = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLH() { + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + + if (_Rt_) { + _i32(_rRt_) = (short)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLHU() { + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + + if (_Rt_) { + _u32(_rRt_) = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLW() { + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + + if (_Rt_) { + _u32(_rRt_) = psxMemRead32(_oB_); + } else { + psxMemRead32(_oB_); + } +} + +u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; +u32 LWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void psxLWL() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + if (!_Rt_) return; + _u32(_rRt_) = ( _u32(_rRt_) & 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 psxLWR() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + + + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + + if (!_Rt_) return; + _u32(_rRt_) = ( _u32(_rRt_) & 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 psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); } +void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); } +void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); } + +u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 }; +u32 SWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void psxSWL() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + psxMemWrite32(addr & ~3, (_u32(_rRt_) >> 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] = { 0, 0xff, 0xffff, 0xffffff }; +u32 SWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void psxSWR() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + psxMemWrite32(addr & ~3, (_u32(_rRt_) << 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) + */ +} + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +void psxMFC0() +{ + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + if (!_Rt_) return; + + _i32(_rRt_) = (int)_rFs_; +} + +void psxCFC0() +{ + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + + if (!_Rt_) return; + + _i32(_rRt_) = (int)_rFs_; +} + +void psxTestSWInts() { + // the next code is untested, if u know please + // tell me if it works ok or not (linuzappz) + if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 && + psxRegs.CP0.n.Status & 0x1) { + psxException(psxRegs.CP0.n.Cause, branch); + } +} + +static __inline void MTC0(int reg, u32 val) { +// SysPrintf("MTC0 %d: %x\n", reg, val); + switch (reg) { + case 12: // Status + psxRegs.CP0.r[12] = val; + psxTestSWInts(); + break; + + case 13: // Cause + psxRegs.CP0.n.Cause = val & ~(0xfc00); + psxTestSWInts(); + break; + + default: + psxRegs.CP0.r[reg] = val; + break; + } +} + +void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); } +void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); } + + + +void psxMFC2() +{ + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + gteMFC2(); +} + + +void psxCFC2() +{ + // load delay = 1 latency + if( branch == 0 ) + { + // simulate: beq r0,r0,lw+4 / lw / (delay slot) + psxRegs.pc -= 4; + doBranch( psxRegs.pc + 4 ); + + return; + } + + gteCFC2(); +} + + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +void psxNULL() { +#ifdef PSXCPU_LOG + PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code); +#endif +} + +void psxSPECIAL() { + psxSPC[_Funct_](); +} + +void psxREGIMM() { + psxREG[_Rt_](); +} + +void psxCOP0() { + psxCP0[_Rs_](); +} + +void psxCOP2() { + if ((psxRegs.CP0.n.Status & 0x40000000) == 0 ) + return; + + psxCP2[_Funct_](); +} + +void psxBASIC() { + psxCP2BSC[_Rs_](); +} + +void psxHLE() { +// psxHLEt[psxRegs.code & 0xffff](); + psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch +} + +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 , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , gteSWC2, psxHLE , 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, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00 + psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08 + gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10 + psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18 + gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20 + gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28 + gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38 +}; + +void (*psxCP2BSC[32])() = { + psxMFC2, psxNULL, psxCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, 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() { + psxRegs.ICache_valid = FALSE; +} + +static void intExecute() { + for (;;) + execI(); +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +// interpreter execution +static inline void execI() { + u32 *code = Read_ICache(psxRegs.pc, FALSE); + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + + debugI(); + + if (Config.Debug) ProcessDebug(); + + psxRegs.pc += 4; + psxRegs.cycle += BIAS; + + psxBSC[psxRegs.code >> 26](); +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +}; diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 14e27305..8215bdaf 100644..100755 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -1,374 +1,374 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* PSX memory functions.
-*/
-
-#include "psxmem.h"
-#include "r3000a.h"
-#include "psxhw.h"
-#include <sys/mman.h>
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-s8 *psxM = NULL; // Kernel & User Memory (2 Meg)
-s8 *psxP = NULL; // Parallel Port (64K)
-s8 *psxR = NULL; // BIOS ROM (512K)
-s8 *psxH = NULL; // Scratch Pad (1K) & Hardware Registers (8K)
-
-u8 **psxMemWLUT = NULL;
-u8 **psxMemRLUT = NULL;
-
-/* Playstation Memory Map (from Playstation doc by Joshua Walker)
-0x0000_0000-0x0000_ffff Kernel (64K)
-0x0001_0000-0x001f_ffff User Memory (1.9 Meg)
-
-0x1f00_0000-0x1f00_ffff Parallel Port (64K)
-
-0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes)
-
-0x1f80_1000-0x1f80_2fff Hardware Registers (8K)
-
-0x1fc0_0000-0x1fc7_ffff BIOS (512K)
-
-0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached
-0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached
-
-0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached
-0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached
-*/
-
-int psxMemInit() {
- int i;
-
- psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *));
- psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *));
- memset(psxMemRLUT, 0, 0x10000 * sizeof(void *));
- memset(psxMemWLUT, 0, 0x10000 * sizeof(void *));
-
- psxM = mmap(0, 0x00220000,
- PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- psxP = &psxM[0x200000];
- psxH = &psxM[0x210000];
-
- psxR = (s8 *)malloc(0x00080000);
-
- if (psxMemRLUT == NULL || psxMemWLUT == NULL ||
- psxM == NULL || psxP == NULL || psxH == NULL) {
- SysMessage(_("Error allocating memory!"));
- return -1;
- }
-
-// MemR
- for (i = 0; i < 0x80; i++) psxMemRLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16];
-
- memcpy(psxMemRLUT + 0x8000, psxMemRLUT, 0x80 * sizeof(void *));
- memcpy(psxMemRLUT + 0xa000, psxMemRLUT, 0x80 * sizeof(void *));
-
- psxMemRLUT[0x1f00] = (u8 *)psxP;
- psxMemRLUT[0x1f80] = (u8 *)psxH;
-
- for (i = 0; i < 0x08; i++) psxMemRLUT[i + 0x1fc0] = (u8 *)&psxR[i << 16];
-
- memcpy(psxMemRLUT + 0x9fc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *));
- memcpy(psxMemRLUT + 0xbfc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *));
-
-// MemW
- for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16];
-
- memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *));
- memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *));
-
- psxMemWLUT[0x1f00] = (u8 *)psxP;
- psxMemWLUT[0x1f80] = (u8 *)psxH;
-
- return 0;
-}
-
-void psxMemReset() {
- FILE *f = NULL;
- char bios[1024];
-
- memset(psxM, 0, 0x00200000);
- memset(psxP, 0, 0x00010000);
-
- // Load BIOS
- if (strcmp(Config.Bios, "HLE") != 0) {
- sprintf(bios, "%s/%s", Config.BiosDir, Config.Bios);
- f = fopen(bios, "rb");
-
- if (f == NULL) {
- SysMessage(_("Could not open BIOS:\"%s\". Enabling HLE Bios!\n"), bios);
- memset(psxR, 0, 0x80000);
- Config.HLE = TRUE;
- } else {
- fread(psxR, 1, 0x80000, f);
- fclose(f);
- Config.HLE = FALSE;
- }
- } else Config.HLE = TRUE;
-}
-
-void psxMemShutdown() {
- munmap(psxM, 0x00220000);
-
- free(psxR);
- free(psxMemRLUT);
- free(psxMemWLUT);
-}
-
-static int writeok = 1;
-
-u8 psxMemRead8(u32 mem) {
- char *p;
- u32 t;
-
-
- psxRegs.cycle += 0;
-
-
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- return psxHu8(mem);
- else
- return psxHwRead8(mem);
- } else {
- p = (char *)(psxMemRLUT[t]);
- if (p != NULL) {
- if (Config.Debug)
- DebugCheckBP((mem & 0xffffff) | 0x80000000, BR1);
- return *(u8 *)(p + (mem & 0xffff));
- } else {
-#ifdef PSXMEM_LOG
- PSXMEM_LOG("err lb %8.8lx\n", mem);
-#endif
- return 0;
- }
- }
-}
-
-u16 psxMemRead16(u32 mem) {
- char *p;
- u32 t;
-
-
- psxRegs.cycle += 1;
-
-
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- return psxHu16(mem);
- else
- return psxHwRead16(mem);
- } else {
- p = (char *)(psxMemRLUT[t]);
- if (p != NULL) {
- if (Config.Debug)
- DebugCheckBP((mem & 0xffffff) | 0x80000000, BR2);
- return SWAPu16(*(u16 *)(p + (mem & 0xffff)));
- } else {
-#ifdef PSXMEM_LOG
- PSXMEM_LOG("err lh %8.8lx\n", mem);
-#endif
- return 0;
- }
- }
-}
-
-u32 psxMemRead32(u32 mem) {
- char *p;
- u32 t;
-
-
- psxRegs.cycle += 1;
-
-
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- return psxHu32(mem);
- else
- return psxHwRead32(mem);
- } else {
- p = (char *)(psxMemRLUT[t]);
- if (p != NULL) {
- if (Config.Debug)
- DebugCheckBP((mem & 0xffffff) | 0x80000000, BR4);
- return SWAPu32(*(u32 *)(p + (mem & 0xffff)));
- } else {
-#ifdef PSXMEM_LOG
- if (writeok) { PSXMEM_LOG("err lw %8.8lx\n", mem); }
-#endif
- return 0;
- }
- }
-}
-
-void psxMemWrite8(u32 mem, u8 value) {
- char *p;
- u32 t;
-
-
- psxRegs.cycle += 1;
-
-
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- psxHu8(mem) = value;
- else
- psxHwWrite8(mem, value);
- } else {
- p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
- if (Config.Debug)
- DebugCheckBP((mem & 0xffffff) | 0x80000000, BW1);
- *(u8 *)(p + (mem & 0xffff)) = value;
-#ifdef PSXREC
- psxCpu->Clear((mem & (~3)), 1);
-#endif
- } else {
-#ifdef PSXMEM_LOG
- PSXMEM_LOG("err sb %8.8lx\n", mem);
-#endif
- }
- }
-}
-
-void psxMemWrite16(u32 mem, u16 value) {
- char *p;
- u32 t;
-
-
- psxRegs.cycle += 1;
-
-
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- psxHu16ref(mem) = SWAPu16(value);
- else
- psxHwWrite16(mem, value);
- } else {
- p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
- if (Config.Debug)
- DebugCheckBP((mem & 0xffffff) | 0x80000000, BW2);
- *(u16 *)(p + (mem & 0xffff)) = SWAPu16(value);
-#ifdef PSXREC
- psxCpu->Clear((mem & (~3)), 1);
-#endif
- } else {
-#ifdef PSXMEM_LOG
- PSXMEM_LOG("err sh %8.8lx\n", mem);
-#endif
- }
- }
-}
-
-void psxMemWrite32(u32 mem, u32 value) {
- char *p;
- u32 t;
-
-
- psxRegs.cycle += 1;
-
-
- // if ((mem&0x1fffff) == 0x71E18 || value == 0x48088800) SysPrintf("t2fix!!\n");
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- psxHu32ref(mem) = SWAPu32(value);
- else
- psxHwWrite32(mem, value);
- } else {
- p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
- if (Config.Debug)
- DebugCheckBP((mem & 0xffffff) | 0x80000000, BW4);
- *(u32 *)(p + (mem & 0xffff)) = SWAPu32(value);
-#ifdef PSXREC
- psxCpu->Clear(mem, 1);
-#endif
- } else {
- if (mem != 0xfffe0130) {
-#ifdef PSXREC
- if (!writeok)
- psxCpu->Clear(mem, 1);
-#endif
-
-#ifdef PSXMEM_LOG
- if (writeok) { PSXMEM_LOG("err sw %8.8lx\n", mem); }
-#endif
- } else {
- int i;
-
- // a0-44: used for cache flushing
- switch (value) {
- case 0x800: case 0x804:
- if (writeok == 0) break;
- writeok = 0;
- memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(void *));
- memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(void *));
- memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(void *));
-
- psxRegs.ICache_valid = 0;
- break;
- case 0x00: case 0x1e988:
- if (writeok == 1) break;
- writeok = 1;
- for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (void *)&psxM[(i & 0x1f) << 16];
- memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *));
- memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *));
- break;
- default:
-#ifdef PSXMEM_LOG
- PSXMEM_LOG("unk %8.8lx = %x\n", mem, value);
-#endif
- break;
- }
- }
- }
- }
-}
-
-void *psxMemPointer(u32 mem) {
- char *p;
- u32 t;
-
- t = mem >> 16;
- if (t == 0x1f80) {
- if (mem < 0x1f801000)
- return (void *)&psxH[mem];
- else
- return NULL;
- } else {
- p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
- return (void *)(p + (mem & 0xffff));
- }
- return NULL;
- }
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* PSX memory functions. +*/ + +#include "psxmem.h" +#include "r3000a.h" +#include "psxhw.h" +#include <sys/mman.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +s8 *psxM = NULL; // Kernel & User Memory (2 Meg) +s8 *psxP = NULL; // Parallel Port (64K) +s8 *psxR = NULL; // BIOS ROM (512K) +s8 *psxH = NULL; // Scratch Pad (1K) & Hardware Registers (8K) + +u8 **psxMemWLUT = NULL; +u8 **psxMemRLUT = NULL; + +/* Playstation Memory Map (from Playstation doc by Joshua Walker) +0x0000_0000-0x0000_ffff Kernel (64K) +0x0001_0000-0x001f_ffff User Memory (1.9 Meg) + +0x1f00_0000-0x1f00_ffff Parallel Port (64K) + +0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes) + +0x1f80_1000-0x1f80_2fff Hardware Registers (8K) + +0x1fc0_0000-0x1fc7_ffff BIOS (512K) + +0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached +0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached + +0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached +0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached +*/ + +int psxMemInit() { + int i; + + psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *)); + psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *)); + memset(psxMemRLUT, 0, 0x10000 * sizeof(void *)); + memset(psxMemWLUT, 0, 0x10000 * sizeof(void *)); + + psxM = mmap(0, 0x00220000, + PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + psxP = &psxM[0x200000]; + psxH = &psxM[0x210000]; + + psxR = (s8 *)malloc(0x00080000); + + if (psxMemRLUT == NULL || psxMemWLUT == NULL || + psxM == NULL || psxP == NULL || psxH == NULL) { + SysMessage(_("Error allocating memory!")); + return -1; + } + +// MemR + for (i = 0; i < 0x80; i++) psxMemRLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16]; + + memcpy(psxMemRLUT + 0x8000, psxMemRLUT, 0x80 * sizeof(void *)); + memcpy(psxMemRLUT + 0xa000, psxMemRLUT, 0x80 * sizeof(void *)); + + psxMemRLUT[0x1f00] = (u8 *)psxP; + psxMemRLUT[0x1f80] = (u8 *)psxH; + + for (i = 0; i < 0x08; i++) psxMemRLUT[i + 0x1fc0] = (u8 *)&psxR[i << 16]; + + memcpy(psxMemRLUT + 0x9fc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *)); + memcpy(psxMemRLUT + 0xbfc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *)); + +// MemW + for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16]; + + memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); + memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); + + psxMemWLUT[0x1f00] = (u8 *)psxP; + psxMemWLUT[0x1f80] = (u8 *)psxH; + + return 0; +} + +void psxMemReset() { + FILE *f = NULL; + char bios[1024]; + + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + + // Load BIOS + if (strcmp(Config.Bios, "HLE") != 0) { + sprintf(bios, "%s/%s", Config.BiosDir, Config.Bios); + f = fopen(bios, "rb"); + + if (f == NULL) { + SysMessage(_("Could not open BIOS:\"%s\". Enabling HLE Bios!\n"), bios); + memset(psxR, 0, 0x80000); + Config.HLE = TRUE; + } else { + fread(psxR, 1, 0x80000, f); + fclose(f); + Config.HLE = FALSE; + } + } else Config.HLE = TRUE; +} + +void psxMemShutdown() { + munmap(psxM, 0x00220000); + + free(psxR); + free(psxMemRLUT); + free(psxMemWLUT); +} + +static int writeok = 1; + +u8 psxMemRead8(u32 mem) { + char *p; + u32 t; + + + psxRegs.cycle += 0; + + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + } else { + p = (char *)(psxMemRLUT[t]); + if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, BR1); + return *(u8 *)(p + (mem & 0xffff)); + } else { +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lb %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u16 psxMemRead16(u32 mem) { + char *p; + u32 t; + + + psxRegs.cycle += 1; + + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + } else { + p = (char *)(psxMemRLUT[t]); + if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, BR2); + return SWAPu16(*(u16 *)(p + (mem & 0xffff))); + } else { +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lh %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u32 psxMemRead32(u32 mem) { + char *p; + u32 t; + + + psxRegs.cycle += 1; + + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + } else { + p = (char *)(psxMemRLUT[t]); + if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, BR4); + return SWAPu32(*(u32 *)(p + (mem & 0xffff))); + } else { +#ifdef PSXMEM_LOG + if (writeok) { PSXMEM_LOG("err lw %8.8lx\n", mem); } +#endif + return 0; + } + } +} + +void psxMemWrite8(u32 mem, u8 value) { + char *p; + u32 t; + + + psxRegs.cycle += 1; + + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + } else { + p = (char *)(psxMemWLUT[t]); + if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, BW1); + *(u8 *)(p + (mem & 0xffff)) = value; +#ifdef PSXREC + psxCpu->Clear((mem & (~3)), 1); +#endif + } else { +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sb %8.8lx\n", mem); +#endif + } + } +} + +void psxMemWrite16(u32 mem, u16 value) { + char *p; + u32 t; + + + psxRegs.cycle += 1; + + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + psxHu16ref(mem) = SWAPu16(value); + else + psxHwWrite16(mem, value); + } else { + p = (char *)(psxMemWLUT[t]); + if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, BW2); + *(u16 *)(p + (mem & 0xffff)) = SWAPu16(value); +#ifdef PSXREC + psxCpu->Clear((mem & (~3)), 1); +#endif + } else { +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sh %8.8lx\n", mem); +#endif + } + } +} + +void psxMemWrite32(u32 mem, u32 value) { + char *p; + u32 t; + + + psxRegs.cycle += 1; + + + // if ((mem&0x1fffff) == 0x71E18 || value == 0x48088800) SysPrintf("t2fix!!\n"); + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + psxHu32ref(mem) = SWAPu32(value); + else + psxHwWrite32(mem, value); + } else { + p = (char *)(psxMemWLUT[t]); + if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, BW4); + *(u32 *)(p + (mem & 0xffff)) = SWAPu32(value); +#ifdef PSXREC + psxCpu->Clear(mem, 1); +#endif + } else { + if (mem != 0xfffe0130) { +#ifdef PSXREC + if (!writeok) + psxCpu->Clear(mem, 1); +#endif + +#ifdef PSXMEM_LOG + if (writeok) { PSXMEM_LOG("err sw %8.8lx\n", mem); } +#endif + } else { + int i; + + // a0-44: used for cache flushing + switch (value) { + case 0x800: case 0x804: + if (writeok == 0) break; + writeok = 0; + memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(void *)); + memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(void *)); + memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(void *)); + + psxRegs.ICache_valid = 0; + break; + case 0x00: case 0x1e988: + if (writeok == 1) break; + writeok = 1; + for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (void *)&psxM[(i & 0x1f) << 16]; + memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); + memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + } + } +} + +void *psxMemPointer(u32 mem) { + char *p; + u32 t; + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return (void *)&psxH[mem]; + else + return NULL; + } else { + p = (char *)(psxMemWLUT[t]); + if (p != NULL) { + return (void *)(p + (mem & 0xffff)); + } + return NULL; + } +} diff --git a/libpcsxcore/psxmem.h b/libpcsxcore/psxmem.h index 24bc9e38..08d16197 100644..100755 --- a/libpcsxcore/psxmem.h +++ b/libpcsxcore/psxmem.h @@ -1,144 +1,144 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#ifndef __PSXMEMORY_H__
-#define __PSXMEMORY_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "psxcommon.h"
-
-#if defined(__BIGENDIAN__)
-
-#define _SWAP16(b) ((((unsigned char *)&(b))[0] & 0xff) | (((unsigned char *)&(b))[1] & 0xff) << 8)
-#define _SWAP32(b) ((((unsigned char *)&(b))[0] & 0xff) | ((((unsigned char *)&(b))[1] & 0xff) << 8) | ((((unsigned char *)&(b))[2] & 0xff) << 16) | (((unsigned char *)&(b))[3] << 24))
-
-#define SWAP16(v) ((((v) & 0xff00) >> 8) +(((v) & 0xff) << 8))
-#define SWAP32(v) ((((v) & 0xff000000ul) >> 24) + (((v) & 0xff0000ul) >> 8) + (((v) & 0xff00ul)<<8) +(((v) & 0xfful) << 24))
-#define SWAPu32(v) SWAP32((u32)(v))
-#define SWAPs32(v) SWAP32((s32)(v))
-
-#define SWAPu16(v) SWAP16((u16)(v))
-#define SWAPs16(v) SWAP16((s16)(v))
-
-#else
-
-#define SWAP16(b) (b)
-#define SWAP32(b) (b)
-
-#define SWAPu16(b) (b)
-#define SWAPu32(b) (b)
-
-#endif
-
-extern s8 *psxM;
-#define psxMs8(mem) psxM[(mem) & 0x1fffff]
-#define psxMs16(mem) (SWAP16(*(s16 *)&psxM[(mem) & 0x1fffff]))
-#define psxMs32(mem) (SWAP32(*(s32 *)&psxM[(mem) & 0x1fffff]))
-#define psxMu8(mem) (*(u8 *)&psxM[(mem) & 0x1fffff])
-#define psxMu16(mem) (SWAP16(*(u16 *)&psxM[(mem) & 0x1fffff]))
-#define psxMu32(mem) (SWAP32(*(u32 *)&psxM[(mem) & 0x1fffff]))
-
-#define psxMs8ref(mem) psxM[(mem) & 0x1fffff]
-#define psxMs16ref(mem) (*(s16 *)&psxM[(mem) & 0x1fffff])
-#define psxMs32ref(mem) (*(s32 *)&psxM[(mem) & 0x1fffff])
-#define psxMu8ref(mem) (*(u8 *)&psxM[(mem) & 0x1fffff])
-#define psxMu16ref(mem) (*(u16 *)&psxM[(mem) & 0x1fffff])
-#define psxMu32ref(mem) (*(u32 *)&psxM[(mem) & 0x1fffff])
-
-extern s8 *psxP;
-#define psxPs8(mem) psxP[(mem) & 0xffff]
-#define psxPs16(mem) (SWAP16(*(s16 *)&psxP[(mem) & 0xffff]))
-#define psxPs32(mem) (SWAP32(*(s32 *)&psxP[(mem) & 0xffff]))
-#define psxPu8(mem) (*(u8 *)&psxP[(mem) & 0xffff])
-#define psxPu16(mem) (SWAP16(*(u16 *)&psxP[(mem) & 0xffff]))
-#define psxPu32(mem) (SWAP32(*(u32 *)&psxP[(mem) & 0xffff]))
-
-#define psxPs8ref(mem) psxP[(mem) & 0xffff]
-#define psxPs16ref(mem) (*(s16 *)&psxP[(mem) & 0xffff])
-#define psxPs32ref(mem) (*(s32 *)&psxP[(mem) & 0xffff])
-#define psxPu8ref(mem) (*(u8 *)&psxP[(mem) & 0xffff])
-#define psxPu16ref(mem) (*(u16 *)&psxP[(mem) & 0xffff])
-#define psxPu32ref(mem) (*(u32 *)&psxP[(mem) & 0xffff])
-
-extern s8 *psxR;
-#define psxRs8(mem) psxR[(mem) & 0x7ffff]
-#define psxRs16(mem) (SWAP16(*(s16 *)&psxR[(mem) & 0x7ffff]))
-#define psxRs32(mem) (SWAP32(*(s32 *)&psxR[(mem) & 0x7ffff]))
-#define psxRu8(mem) (*(u8* )&psxR[(mem) & 0x7ffff])
-#define psxRu16(mem) (SWAP16(*(u16 *)&psxR[(mem) & 0x7ffff]))
-#define psxRu32(mem) (SWAP32(*(u32 *)&psxR[(mem) & 0x7ffff]))
-
-#define psxRs8ref(mem) psxR[(mem) & 0x7ffff]
-#define psxRs16ref(mem) (*(s16*)&psxR[(mem) & 0x7ffff])
-#define psxRs32ref(mem) (*(s32*)&psxR[(mem) & 0x7ffff])
-#define psxRu8ref(mem) (*(u8 *)&psxR[(mem) & 0x7ffff])
-#define psxRu16ref(mem) (*(u16*)&psxR[(mem) & 0x7ffff])
-#define psxRu32ref(mem) (*(u32*)&psxR[(mem) & 0x7ffff])
-
-extern s8 *psxH;
-#define psxHs8(mem) psxH[(mem) & 0xffff]
-#define psxHs16(mem) (SWAP16(*(s16 *)&psxH[(mem) & 0xffff]))
-#define psxHs32(mem) (SWAP32(*(s32 *)&psxH[(mem) & 0xffff]))
-#define psxHu8(mem) (*(u8 *)&psxH[(mem) & 0xffff])
-#define psxHu16(mem) (SWAP16(*(u16 *)&psxH[(mem) & 0xffff]))
-#define psxHu32(mem) (SWAP32(*(u32 *)&psxH[(mem) & 0xffff]))
-
-#define psxHs8ref(mem) psxH[(mem) & 0xffff]
-#define psxHs16ref(mem) (*(s16 *)&psxH[(mem) & 0xffff])
-#define psxHs32ref(mem) (*(s32 *)&psxH[(mem) & 0xffff])
-#define psxHu8ref(mem) (*(u8 *)&psxH[(mem) & 0xffff])
-#define psxHu16ref(mem) (*(u16 *)&psxH[(mem) & 0xffff])
-#define psxHu32ref(mem) (*(u32 *)&psxH[(mem) & 0xffff])
-
-extern u8 **psxMemWLUT;
-extern u8 **psxMemRLUT;
-
-#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (u8*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)))
-#define PSXMs8(mem) (*(s8 *)PSXM(mem))
-#define PSXMs16(mem) (SWAP16(*(s16 *)PSXM(mem)))
-#define PSXMs32(mem) (SWAP32(*(s32 *)PSXM(mem)))
-#define PSXMu8(mem) (*(u8 *)PSXM(mem))
-#define PSXMu16(mem) (SWAP16(*(u16 *)PSXM(mem)))
-#define PSXMu32(mem) (SWAP32(*(u32 *)PSXM(mem)))
-
-#define PSXMu32ref(mem) (*(u32 *)PSXM(mem))
-
-#if !defined(PSXREC) && (defined(__x86_64__) || defined(__i386__) || defined(__ppc__)) && !defined(NOPSXREC)
-#define PSXREC
-#endif
-
-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);
-void *psxMemPointer(u32 mem);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef __PSXMEMORY_H__ +#define __PSXMEMORY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psxcommon.h" + +#if defined(__BIGENDIAN__) + +#define _SWAP16(b) ((((unsigned char *)&(b))[0] & 0xff) | (((unsigned char *)&(b))[1] & 0xff) << 8) +#define _SWAP32(b) ((((unsigned char *)&(b))[0] & 0xff) | ((((unsigned char *)&(b))[1] & 0xff) << 8) | ((((unsigned char *)&(b))[2] & 0xff) << 16) | (((unsigned char *)&(b))[3] << 24)) + +#define SWAP16(v) ((((v) & 0xff00) >> 8) +(((v) & 0xff) << 8)) +#define SWAP32(v) ((((v) & 0xff000000ul) >> 24) + (((v) & 0xff0000ul) >> 8) + (((v) & 0xff00ul)<<8) +(((v) & 0xfful) << 24)) +#define SWAPu32(v) SWAP32((u32)(v)) +#define SWAPs32(v) SWAP32((s32)(v)) + +#define SWAPu16(v) SWAP16((u16)(v)) +#define SWAPs16(v) SWAP16((s16)(v)) + +#else + +#define SWAP16(b) (b) +#define SWAP32(b) (b) + +#define SWAPu16(b) (b) +#define SWAPu32(b) (b) + +#endif + +extern s8 *psxM; +#define psxMs8(mem) psxM[(mem) & 0x1fffff] +#define psxMs16(mem) (SWAP16(*(s16 *)&psxM[(mem) & 0x1fffff])) +#define psxMs32(mem) (SWAP32(*(s32 *)&psxM[(mem) & 0x1fffff])) +#define psxMu8(mem) (*(u8 *)&psxM[(mem) & 0x1fffff]) +#define psxMu16(mem) (SWAP16(*(u16 *)&psxM[(mem) & 0x1fffff])) +#define psxMu32(mem) (SWAP32(*(u32 *)&psxM[(mem) & 0x1fffff])) + +#define psxMs8ref(mem) psxM[(mem) & 0x1fffff] +#define psxMs16ref(mem) (*(s16 *)&psxM[(mem) & 0x1fffff]) +#define psxMs32ref(mem) (*(s32 *)&psxM[(mem) & 0x1fffff]) +#define psxMu8ref(mem) (*(u8 *)&psxM[(mem) & 0x1fffff]) +#define psxMu16ref(mem) (*(u16 *)&psxM[(mem) & 0x1fffff]) +#define psxMu32ref(mem) (*(u32 *)&psxM[(mem) & 0x1fffff]) + +extern s8 *psxP; +#define psxPs8(mem) psxP[(mem) & 0xffff] +#define psxPs16(mem) (SWAP16(*(s16 *)&psxP[(mem) & 0xffff])) +#define psxPs32(mem) (SWAP32(*(s32 *)&psxP[(mem) & 0xffff])) +#define psxPu8(mem) (*(u8 *)&psxP[(mem) & 0xffff]) +#define psxPu16(mem) (SWAP16(*(u16 *)&psxP[(mem) & 0xffff])) +#define psxPu32(mem) (SWAP32(*(u32 *)&psxP[(mem) & 0xffff])) + +#define psxPs8ref(mem) psxP[(mem) & 0xffff] +#define psxPs16ref(mem) (*(s16 *)&psxP[(mem) & 0xffff]) +#define psxPs32ref(mem) (*(s32 *)&psxP[(mem) & 0xffff]) +#define psxPu8ref(mem) (*(u8 *)&psxP[(mem) & 0xffff]) +#define psxPu16ref(mem) (*(u16 *)&psxP[(mem) & 0xffff]) +#define psxPu32ref(mem) (*(u32 *)&psxP[(mem) & 0xffff]) + +extern s8 *psxR; +#define psxRs8(mem) psxR[(mem) & 0x7ffff] +#define psxRs16(mem) (SWAP16(*(s16 *)&psxR[(mem) & 0x7ffff])) +#define psxRs32(mem) (SWAP32(*(s32 *)&psxR[(mem) & 0x7ffff])) +#define psxRu8(mem) (*(u8* )&psxR[(mem) & 0x7ffff]) +#define psxRu16(mem) (SWAP16(*(u16 *)&psxR[(mem) & 0x7ffff])) +#define psxRu32(mem) (SWAP32(*(u32 *)&psxR[(mem) & 0x7ffff])) + +#define psxRs8ref(mem) psxR[(mem) & 0x7ffff] +#define psxRs16ref(mem) (*(s16*)&psxR[(mem) & 0x7ffff]) +#define psxRs32ref(mem) (*(s32*)&psxR[(mem) & 0x7ffff]) +#define psxRu8ref(mem) (*(u8 *)&psxR[(mem) & 0x7ffff]) +#define psxRu16ref(mem) (*(u16*)&psxR[(mem) & 0x7ffff]) +#define psxRu32ref(mem) (*(u32*)&psxR[(mem) & 0x7ffff]) + +extern s8 *psxH; +#define psxHs8(mem) psxH[(mem) & 0xffff] +#define psxHs16(mem) (SWAP16(*(s16 *)&psxH[(mem) & 0xffff])) +#define psxHs32(mem) (SWAP32(*(s32 *)&psxH[(mem) & 0xffff])) +#define psxHu8(mem) (*(u8 *)&psxH[(mem) & 0xffff]) +#define psxHu16(mem) (SWAP16(*(u16 *)&psxH[(mem) & 0xffff])) +#define psxHu32(mem) (SWAP32(*(u32 *)&psxH[(mem) & 0xffff])) + +#define psxHs8ref(mem) psxH[(mem) & 0xffff] +#define psxHs16ref(mem) (*(s16 *)&psxH[(mem) & 0xffff]) +#define psxHs32ref(mem) (*(s32 *)&psxH[(mem) & 0xffff]) +#define psxHu8ref(mem) (*(u8 *)&psxH[(mem) & 0xffff]) +#define psxHu16ref(mem) (*(u16 *)&psxH[(mem) & 0xffff]) +#define psxHu32ref(mem) (*(u32 *)&psxH[(mem) & 0xffff]) + +extern u8 **psxMemWLUT; +extern u8 **psxMemRLUT; + +#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (u8*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) +#define PSXMs8(mem) (*(s8 *)PSXM(mem)) +#define PSXMs16(mem) (SWAP16(*(s16 *)PSXM(mem))) +#define PSXMs32(mem) (SWAP32(*(s32 *)PSXM(mem))) +#define PSXMu8(mem) (*(u8 *)PSXM(mem)) +#define PSXMu16(mem) (SWAP16(*(u16 *)PSXM(mem))) +#define PSXMu32(mem) (SWAP32(*(u32 *)PSXM(mem))) + +#define PSXMu32ref(mem) (*(u32 *)PSXM(mem)) + +#if !defined(PSXREC) && (defined(__x86_64__) || defined(__i386__) || defined(__ppc__)) && !defined(NOPSXREC) +#define PSXREC +#endif + +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); +void *psxMemPointer(u32 mem); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index c7a2b09a..957908d1 100644..100755 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -1,267 +1,267 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* R3000A CPU functions.
-*/
-
-#include "r3000a.h"
-#include "cdrom.h"
-#include "mdec.h"
-#include "gpu.h"
-#include "gte.h"
-
-R3000Acpu *psxCpu = NULL;
-psxRegisters psxRegs;
-
-int psxInit() {
- SysPrintf(_("Running PCSXR Version %s (%s).\n"), PACKAGE_VERSION, __DATE__);
-
-#ifdef PSXREC
- if (Config.Cpu == CPU_INTERPRETER) {
- psxCpu = &psxInt;
- } else psxCpu = &psxRec;
-#else
- psxCpu = &psxInt;
-#endif
-
- Log = 0;
-
- 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.r[12] = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
- psxRegs.CP0.r[15] = 0x00000002; // PRevID = Revision ID, same as R3000A
-
- psxHwReset();
- psxBiosInit();
-
- if (!Config.HLE)
- psxExecuteBios();
-
-#ifdef EMU_LOG
- EMU_LOG("*BIOS END*\n");
-#endif
- Log = 0;
-}
-
-void psxShutdown() {
- psxMemShutdown();
- psxBiosShutdown();
-
- psxCpu->Shutdown();
-}
-
-void psxException(u32 code, u32 bd) {
- // Set the Cause
- psxRegs.CP0.n.Cause = code;
-
- // Set the EPC & PC
- if (bd) {
-#ifdef PSXCPU_LOG
- PSXCPU_LOG("bd set!!!\n");
-#endif
- SysPrintf("bd set!!!\n");
- 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 (Config.HLE) psxBiosException();
-}
-
-void psxBranchTest() {
- // GameShark Sampler: Give VSync pin some delay before exception eats it
- if (psxHu32(0x1070) & psxHu32(0x1074)) {
- if ((psxRegs.CP0.n.Status & 0x401) == 0x401) {
- u32 opcode;
-
- // Crash Bandicoot 2: Don't run exceptions when GTE in pipeline
- opcode = SWAP32(*Read_ICache(psxRegs.pc, TRUE));
- if( ((opcode >> 24) & 0xfe) != 0x4a ) {
-#ifdef PSXCPU_LOG
- PSXCPU_LOG("Interrupt: %x %x\n", psxHu32(0x1070), psxHu32(0x1074));
-#endif
- psxException(0x400, 0);
- }
- }
- }
-
-#if 0
- if( SPU_async )
- {
- static int init;
- int elapsed;
-
- if( init == 0 ) {
- // 10 apu cycles
- // - Final Fantasy Tactics (distorted - dropped sound effects)
- psxRegs.intCycle[PSXINT_SPUASYNC].cycle = PSXCLK / 44100 * 10;
-
- init = 1;
- }
-
- elapsed = psxRegs.cycle - psxRegs.intCycle[PSXINT_SPUASYNC].sCycle;
- if (elapsed >= psxRegs.intCycle[PSXINT_SPUASYNC].cycle) {
- SPU_async( elapsed );
-
- psxRegs.intCycle[PSXINT_SPUASYNC].sCycle = psxRegs.cycle;
- }
- }
-#endif
-
- if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
- psxRcntUpdate();
-
- if (psxRegs.interrupt) {
- if ((psxRegs.interrupt & (1 << PSXINT_SIO)) && !Config.Sio) { // sio
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_SIO].sCycle) >= psxRegs.intCycle[PSXINT_SIO].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_SIO);
- sioInterrupt();
- }
- }
- if (psxRegs.interrupt & (1 << PSXINT_CDR)) { // cdr
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDR].sCycle) >= psxRegs.intCycle[PSXINT_CDR].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_CDR);
- cdrInterrupt();
- }
- }
- if (psxRegs.interrupt & (1 << PSXINT_CDREAD)) { // cdr read
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDREAD].sCycle) >= psxRegs.intCycle[PSXINT_CDREAD].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_CDREAD);
- cdrReadInterrupt();
- }
- }
- if (psxRegs.interrupt & (1 << PSXINT_GPUDMA)) { // gpu dma
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_GPUDMA].sCycle) >= psxRegs.intCycle[PSXINT_GPUDMA].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_GPUDMA);
- gpuInterrupt();
- }
- }
- if (psxRegs.interrupt & (1 << PSXINT_MDECOUTDMA)) { // mdec out dma
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_MDECOUTDMA].sCycle) >= psxRegs.intCycle[PSXINT_MDECOUTDMA].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_MDECOUTDMA);
- mdec1Interrupt();
- }
- }
- if (psxRegs.interrupt & (1 << PSXINT_SPUDMA)) { // spu dma
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_SPUDMA].sCycle) >= psxRegs.intCycle[PSXINT_SPUDMA].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_SPUDMA);
- spuInterrupt();
- }
- }
- if (psxRegs.interrupt & (1 << PSXINT_MDECINDMA)) { // mdec in
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_MDECINDMA].sCycle) >= psxRegs.intCycle[PSXINT_MDECINDMA].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_MDECINDMA);
- mdec0Interrupt();
- }
- }
-
- if (psxRegs.interrupt & (1 << PSXINT_GPUOTCDMA)) { // gpu otc
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_GPUOTCDMA].sCycle) >= psxRegs.intCycle[PSXINT_GPUOTCDMA].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_GPUOTCDMA);
- gpuotcInterrupt();
- }
- }
-
- if (psxRegs.interrupt & (1 << PSXINT_CDRDMA)) { // cdrom
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRDMA].sCycle) >= psxRegs.intCycle[PSXINT_CDRDMA].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_CDRDMA);
- cdrDmaInterrupt();
- }
- }
-
- if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY)) { // cdr play timing
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRPLAY].sCycle) >= psxRegs.intCycle[PSXINT_CDRPLAY].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_CDRPLAY);
- cdrPlayInterrupt();
- }
- }
-
- if (psxRegs.interrupt & (1 << PSXINT_CDRDBUF)) { // cdr decoded buffer
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRDBUF].sCycle) >= psxRegs.intCycle[PSXINT_CDRDBUF].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_CDRDBUF);
- cdrDecodedBufferInterrupt();
- }
- }
-
- if (psxRegs.interrupt & (1 << PSXINT_CDRLID)) { // cdr lid states
- if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRLID].sCycle) >= psxRegs.intCycle[PSXINT_CDRLID].cycle) {
- psxRegs.interrupt &= ~(1 << PSXINT_CDRLID);
- cdrLidSeekInterrupt();
- }
- }
- }
-}
-
-void psxJumpTest() {
- if (!Config.HLE && Config.PsxOut) {
- 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;
- }
- }
-}
-
-void psxExecuteBios() {
- while (psxRegs.pc != 0x80030000)
- psxCpu->ExecuteBlock();
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* R3000A CPU functions. +*/ + +#include "r3000a.h" +#include "cdrom.h" +#include "mdec.h" +#include "gpu.h" +#include "gte.h" + +R3000Acpu *psxCpu = NULL; +psxRegisters psxRegs; + +int psxInit() { + SysPrintf(_("Running PCSXR Version %s (%s).\n"), PACKAGE_VERSION, __DATE__); + +#ifdef PSXREC + if (Config.Cpu == CPU_INTERPRETER) { + psxCpu = &psxInt; + } else psxCpu = &psxRec; +#else + psxCpu = &psxInt; +#endif + + Log = 0; + + 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.r[12] = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1 + psxRegs.CP0.r[15] = 0x00000002; // PRevID = Revision ID, same as R3000A + + psxHwReset(); + psxBiosInit(); + + if (!Config.HLE) + psxExecuteBios(); + +#ifdef EMU_LOG + EMU_LOG("*BIOS END*\n"); +#endif + Log = 0; +} + +void psxShutdown() { + psxMemShutdown(); + psxBiosShutdown(); + + psxCpu->Shutdown(); +} + +void psxException(u32 code, u32 bd) { + // Set the Cause + psxRegs.CP0.n.Cause = code; + + // Set the EPC & PC + if (bd) { +#ifdef PSXCPU_LOG + PSXCPU_LOG("bd set!!!\n"); +#endif + SysPrintf("bd set!!!\n"); + 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 (Config.HLE) psxBiosException(); +} + +void psxBranchTest() { + // GameShark Sampler: Give VSync pin some delay before exception eats it + if (psxHu32(0x1070) & psxHu32(0x1074)) { + if ((psxRegs.CP0.n.Status & 0x401) == 0x401) { + u32 opcode; + + // Crash Bandicoot 2: Don't run exceptions when GTE in pipeline + opcode = SWAP32(*Read_ICache(psxRegs.pc, TRUE)); + if( ((opcode >> 24) & 0xfe) != 0x4a ) { +#ifdef PSXCPU_LOG + PSXCPU_LOG("Interrupt: %x %x\n", psxHu32(0x1070), psxHu32(0x1074)); +#endif + psxException(0x400, 0); + } + } + } + +#if 0 + if( SPU_async ) + { + static int init; + int elapsed; + + if( init == 0 ) { + // 10 apu cycles + // - Final Fantasy Tactics (distorted - dropped sound effects) + psxRegs.intCycle[PSXINT_SPUASYNC].cycle = PSXCLK / 44100 * 10; + + init = 1; + } + + elapsed = psxRegs.cycle - psxRegs.intCycle[PSXINT_SPUASYNC].sCycle; + if (elapsed >= psxRegs.intCycle[PSXINT_SPUASYNC].cycle) { + SPU_async( elapsed ); + + psxRegs.intCycle[PSXINT_SPUASYNC].sCycle = psxRegs.cycle; + } + } +#endif + + if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter) + psxRcntUpdate(); + + if (psxRegs.interrupt) { + if ((psxRegs.interrupt & (1 << PSXINT_SIO)) && !Config.Sio) { // sio + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_SIO].sCycle) >= psxRegs.intCycle[PSXINT_SIO].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_SIO); + sioInterrupt(); + } + } + if (psxRegs.interrupt & (1 << PSXINT_CDR)) { // cdr + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDR].sCycle) >= psxRegs.intCycle[PSXINT_CDR].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDR); + cdrInterrupt(); + } + } + if (psxRegs.interrupt & (1 << PSXINT_CDREAD)) { // cdr read + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDREAD].sCycle) >= psxRegs.intCycle[PSXINT_CDREAD].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); + cdrReadInterrupt(); + } + } + if (psxRegs.interrupt & (1 << PSXINT_GPUDMA)) { // gpu dma + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_GPUDMA].sCycle) >= psxRegs.intCycle[PSXINT_GPUDMA].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_GPUDMA); + gpuInterrupt(); + } + } + if (psxRegs.interrupt & (1 << PSXINT_MDECOUTDMA)) { // mdec out dma + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_MDECOUTDMA].sCycle) >= psxRegs.intCycle[PSXINT_MDECOUTDMA].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_MDECOUTDMA); + mdec1Interrupt(); + } + } + if (psxRegs.interrupt & (1 << PSXINT_SPUDMA)) { // spu dma + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_SPUDMA].sCycle) >= psxRegs.intCycle[PSXINT_SPUDMA].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_SPUDMA); + spuInterrupt(); + } + } + if (psxRegs.interrupt & (1 << PSXINT_MDECINDMA)) { // mdec in + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_MDECINDMA].sCycle) >= psxRegs.intCycle[PSXINT_MDECINDMA].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_MDECINDMA); + mdec0Interrupt(); + } + } + + if (psxRegs.interrupt & (1 << PSXINT_GPUOTCDMA)) { // gpu otc + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_GPUOTCDMA].sCycle) >= psxRegs.intCycle[PSXINT_GPUOTCDMA].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_GPUOTCDMA); + gpuotcInterrupt(); + } + } + + if (psxRegs.interrupt & (1 << PSXINT_CDRDMA)) { // cdrom + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRDMA].sCycle) >= psxRegs.intCycle[PSXINT_CDRDMA].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDRDMA); + cdrDmaInterrupt(); + } + } + + if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY)) { // cdr play timing + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRPLAY].sCycle) >= psxRegs.intCycle[PSXINT_CDRPLAY].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDRPLAY); + cdrPlayInterrupt(); + } + } + + if (psxRegs.interrupt & (1 << PSXINT_CDRDBUF)) { // cdr decoded buffer + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRDBUF].sCycle) >= psxRegs.intCycle[PSXINT_CDRDBUF].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDRDBUF); + cdrDecodedBufferInterrupt(); + } + } + + if (psxRegs.interrupt & (1 << PSXINT_CDRLID)) { // cdr lid states + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRLID].sCycle) >= psxRegs.intCycle[PSXINT_CDRLID].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDRLID); + cdrLidSeekInterrupt(); + } + } + } +} + +void psxJumpTest() { + if (!Config.HLE && Config.PsxOut) { + 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; + } + } +} + +void psxExecuteBios() { + while (psxRegs.pc != 0x80030000) + psxCpu->ExecuteBlock(); +} diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index c927d05a..3207a4d0 100644..100755 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -1,339 +1,339 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-#ifndef __R3000A_H__
-#define __R3000A_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "psxcommon.h"
-#include "psxmem.h"
-#include "psxcounters.h"
-#include "psxbios.h"
-
-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;
-#if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC)
-extern R3000Acpu psxRec;
-#define PSXREC
-#endif
-
-typedef union {
-#if defined(__BIGENDIAN__)
- struct { u8 h3, h2, h, l; } b;
- struct { s8 h3, h2, h, l; } sb;
- struct { u16 h, l; } w;
- struct { s16 h, l; } sw;
-#else
- struct { u8 l, h, h2, h3; } b;
- struct { u16 l, h; } w;
- struct { s8 l, h, h2, h3; } sb;
- struct { s16 l, h; } sw;
-#endif
-} PAIR;
-
-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, lo, hi;
- } n;
- u32 r[34]; /* Lo, Hi in r[32] and r[33] */
- PAIR p[34];
-} psxGPRRegs;
-
-typedef union {
- struct {
- u32 Index, Random, EntryLo0, BPC,
- Context, BDA, PIDMask, DCIC,
- BadVAddr, BDAM, EntryHi, BPCM,
- Status, Cause, EPC, PRid,
- Config, LLAddr, WatchLO, WatchHI,
- XContext, Reserved1, Reserved2, Reserved3,
- Reserved4, Reserved5, ECC, CacheErr,
- TagLo, TagHi, ErrorEPC, Reserved6;
- } n;
- u32 r[32];
-} psxCP0Regs;
-
-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];
- PAIR p[32];
-} psxCP2Data;
-
-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];
- PAIR p[32];
-} psxCP2Ctrl;
-
-enum {
- PSXINT_SIO = 0,
- PSXINT_CDR,
- PSXINT_CDREAD,
- PSXINT_GPUDMA,
- PSXINT_MDECOUTDMA,
- PSXINT_SPUDMA,
- PSXINT_GPUBUSY,
- PSXINT_MDECINDMA,
- PSXINT_GPUOTCDMA,
- PSXINT_CDRDMA,
- PSXINT_SPUASYNC,
- PSXINT_CDRDBUF,
- PSXINT_CDRLID,
- PSXINT_CDRPLAY
-};
-
-typedef struct {
- psxGPRRegs GPR; /* General Purpose Registers */
- psxCP0Regs CP0; /* Coprocessor0 Registers */
- psxCP2Data CP2D; /* Cop2 data registers */
- psxCP2Ctrl CP2C; /* Cop2 control registers */
- u32 pc; /* Program counter */
- u32 code; /* The instruction */
- u32 cycle;
- u32 interrupt;
- struct { u32 sCycle, cycle; } intCycle[32];
- u8 ICache_Addr[0x1000];
- u8 ICache_Code[0x1000];
- boolean ICache_valid;
-} psxRegisters;
-
-extern psxRegisters psxRegs;
-
-/*
-Formula One 2001
-- Use old CPU cache code when the RAM location is
- updated with new code (affects in-game racing)
-
-TODO:
-- I-cache / D-cache swapping
-- Isolate D-cache from RAM
-*/
-
-static inline u32 *Read_ICache(u32 pc, boolean isolate) {
- u32 pc_bank, pc_offset, pc_cache;
- u8 *IAddr, *ICode;
-
- pc_bank = pc >> 24;
- pc_offset = pc & 0xffffff;
- pc_cache = pc & 0xfff;
-
- IAddr = psxRegs.ICache_Addr;
- ICode = psxRegs.ICache_Code;
-
- // clear I-cache
- if (!psxRegs.ICache_valid) {
- memset(psxRegs.ICache_Addr, 0xff, sizeof(psxRegs.ICache_Addr));
- memset(psxRegs.ICache_Code, 0xff, sizeof(psxRegs.ICache_Code));
-
- psxRegs.ICache_valid = TRUE;
- }
-
- // uncached
- if (pc_bank >= 0xa0)
- return (u32 *)PSXM(pc);
-
- // cached - RAM
- if (pc_bank == 0x80 || pc_bank == 0x00) {
- if (SWAP32(*(u32 *)(IAddr + pc_cache)) == pc_offset) {
- // Cache hit - return last opcode used
- return (u32 *)(ICode + pc_cache);
- } else {
- // Cache miss - addresses don't match
- // - default: 0xffffffff (not init)
-
- if (!isolate) {
- // cache line is 4 bytes wide
- pc_offset &= ~0xf;
- pc_cache &= ~0xf;
-
- // address line
- *(u32 *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
- *(u32 *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
- *(u32 *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
- *(u32 *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
-
- // opcode line
- pc_offset = pc & ~0xf;
- *(u32 *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
- *(u32 *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
- *(u32 *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
- *(u32 *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
- }
-
- // normal code
- return (u32 *)PSXM(pc);
- }
- }
-
- /*
- TODO: Probably should add cached BIOS
- */
-
- // default
- return (u32 *)PSXM(pc);
-}
-
-#if defined(__BIGENDIAN__)
-
-#define _i32(x) *(s32 *)&x
-#define _u32(x) x
-
-#define _i16(x) (((short *)&x)[1])
-#define _u16(x) (((unsigned short *)&x)[1])
-
-#define _i8(x) (((char *)&x)[3])
-#define _u8(x) (((unsigned char *)&x)[3])
-
-#else
-
-#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
-
-#endif
-
-/**** R3000A Instruction Macros ****/
-#define _PC_ psxRegs.pc // The next PC to be executed
-
-#define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register
-#define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register
-#define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register
-#define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register
-#define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register
-#define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register
-#define _fIm_(code) ((u16)code) // The immediate part of the instruction register
-#define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register
-
-#define _fImm_(code) ((s16)code) // sign-extended immediate
-#define _fImmU_(code) (code&0xffff) // zero-extended immediate
-
-#define _Op_ _fOp_(psxRegs.code)
-#define _Funct_ _fFunct_(psxRegs.code)
-#define _Rd_ _fRd_(psxRegs.code)
-#define _Rt_ _fRt_(psxRegs.code)
-#define _Rs_ _fRs_(psxRegs.code)
-#define _Sa_ _fSa_(psxRegs.code)
-#define _Im_ _fIm_(psxRegs.code)
-#define _Target_ _fTarget_(psxRegs.code)
-
-#define _Imm_ _fImm_(psxRegs.code)
-#define _ImmU_ _fImmU_(psxRegs.code)
-
-#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_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction
-#define _BranchTarget_ ((s16)_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
-
-int psxInit();
-void psxReset();
-void psxShutdown();
-void psxException(u32 code, u32 bd);
-void psxBranchTest();
-void psxExecuteBios();
-int psxTestLoadDelay(int reg, u32 tmp);
-void psxDelayTest(int reg, u32 bpc);
-void psxTestSWInts();
-void psxJumpTest();
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef __R3000A_H__ +#define __R3000A_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psxcommon.h" +#include "psxmem.h" +#include "psxcounters.h" +#include "psxbios.h" + +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; +#if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC) +extern R3000Acpu psxRec; +#define PSXREC +#endif + +typedef union { +#if defined(__BIGENDIAN__) + struct { u8 h3, h2, h, l; } b; + struct { s8 h3, h2, h, l; } sb; + struct { u16 h, l; } w; + struct { s16 h, l; } sw; +#else + struct { u8 l, h, h2, h3; } b; + struct { u16 l, h; } w; + struct { s8 l, h, h2, h3; } sb; + struct { s16 l, h; } sw; +#endif +} PAIR; + +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, lo, hi; + } n; + u32 r[34]; /* Lo, Hi in r[32] and r[33] */ + PAIR p[34]; +} psxGPRRegs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, BPC, + Context, BDA, PIDMask, DCIC, + BadVAddr, BDAM, EntryHi, BPCM, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + u32 r[32]; +} psxCP0Regs; + +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]; + PAIR p[32]; +} psxCP2Data; + +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]; + PAIR p[32]; +} psxCP2Ctrl; + +enum { + PSXINT_SIO = 0, + PSXINT_CDR, + PSXINT_CDREAD, + PSXINT_GPUDMA, + PSXINT_MDECOUTDMA, + PSXINT_SPUDMA, + PSXINT_GPUBUSY, + PSXINT_MDECINDMA, + PSXINT_GPUOTCDMA, + PSXINT_CDRDMA, + PSXINT_SPUASYNC, + PSXINT_CDRDBUF, + PSXINT_CDRLID, + PSXINT_CDRPLAY +}; + +typedef struct { + psxGPRRegs GPR; /* General Purpose Registers */ + psxCP0Regs CP0; /* Coprocessor0 Registers */ + psxCP2Data CP2D; /* Cop2 data registers */ + psxCP2Ctrl CP2C; /* Cop2 control registers */ + u32 pc; /* Program counter */ + u32 code; /* The instruction */ + u32 cycle; + u32 interrupt; + struct { u32 sCycle, cycle; } intCycle[32]; + u8 ICache_Addr[0x1000]; + u8 ICache_Code[0x1000]; + boolean ICache_valid; +} psxRegisters; + +extern psxRegisters psxRegs; + +/* +Formula One 2001 +- Use old CPU cache code when the RAM location is + updated with new code (affects in-game racing) + +TODO: +- I-cache / D-cache swapping +- Isolate D-cache from RAM +*/ + +static inline u32 *Read_ICache(u32 pc, boolean isolate) { + u32 pc_bank, pc_offset, pc_cache; + u8 *IAddr, *ICode; + + pc_bank = pc >> 24; + pc_offset = pc & 0xffffff; + pc_cache = pc & 0xfff; + + IAddr = psxRegs.ICache_Addr; + ICode = psxRegs.ICache_Code; + + // clear I-cache + if (!psxRegs.ICache_valid) { + memset(psxRegs.ICache_Addr, 0xff, sizeof(psxRegs.ICache_Addr)); + memset(psxRegs.ICache_Code, 0xff, sizeof(psxRegs.ICache_Code)); + + psxRegs.ICache_valid = TRUE; + } + + // uncached + if (pc_bank >= 0xa0) + return (u32 *)PSXM(pc); + + // cached - RAM + if (pc_bank == 0x80 || pc_bank == 0x00) { + if (SWAP32(*(u32 *)(IAddr + pc_cache)) == pc_offset) { + // Cache hit - return last opcode used + return (u32 *)(ICode + pc_cache); + } else { + // Cache miss - addresses don't match + // - default: 0xffffffff (not init) + + if (!isolate) { + // cache line is 4 bytes wide + pc_offset &= ~0xf; + pc_cache &= ~0xf; + + // address line + *(u32 *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0); + *(u32 *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4); + *(u32 *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8); + *(u32 *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc); + + // opcode line + pc_offset = pc & ~0xf; + *(u32 *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0); + *(u32 *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4); + *(u32 *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8); + *(u32 *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc); + } + + // normal code + return (u32 *)PSXM(pc); + } + } + + /* + TODO: Probably should add cached BIOS + */ + + // default + return (u32 *)PSXM(pc); +} + +#if defined(__BIGENDIAN__) + +#define _i32(x) *(s32 *)&x +#define _u32(x) x + +#define _i16(x) (((short *)&x)[1]) +#define _u16(x) (((unsigned short *)&x)[1]) + +#define _i8(x) (((char *)&x)[3]) +#define _u8(x) (((unsigned char *)&x)[3]) + +#else + +#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 + +#endif + +/**** R3000A Instruction Macros ****/ +#define _PC_ psxRegs.pc // The next PC to be executed + +#define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register +#define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register +#define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _fIm_(code) ((u16)code) // The immediate part of the instruction register +#define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register + +#define _fImm_(code) ((s16)code) // sign-extended immediate +#define _fImmU_(code) (code&0xffff) // zero-extended immediate + +#define _Op_ _fOp_(psxRegs.code) +#define _Funct_ _fFunct_(psxRegs.code) +#define _Rd_ _fRd_(psxRegs.code) +#define _Rt_ _fRt_(psxRegs.code) +#define _Rs_ _fRs_(psxRegs.code) +#define _Sa_ _fSa_(psxRegs.code) +#define _Im_ _fIm_(psxRegs.code) +#define _Target_ _fTarget_(psxRegs.code) + +#define _Imm_ _fImm_(psxRegs.code) +#define _ImmU_ _fImmU_(psxRegs.code) + +#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_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ ((s16)_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 + +int psxInit(); +void psxReset(); +void psxShutdown(); +void psxException(u32 code, u32 bd); +void psxBranchTest(); +void psxExecuteBios(); +int psxTestLoadDelay(int reg, u32 tmp); +void psxDelayTest(int reg, u32 bpc); +void psxTestSWInts(); +void psxJumpTest(); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c index 0dd01b39..ace3e94d 100644..100755 --- a/libpcsxcore/sio.c +++ b/libpcsxcore/sio.c @@ -1,1328 +1,1328 @@ -/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
- ***************************************************************************/
-
-/*
-* SIO functions.
-*/
-
-#include "sio.h"
-#include <sys/stat.h>
-
-// 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
-
-// *** FOR WORKS ON PADS AND MEMORY CARDS *****
-
-
-void LoadDongle( char *str );
-void SaveDongle( char *str );
-
-
-#define BUFFER_SIZE 0x1010
-
-static unsigned char buf[ BUFFER_SIZE ];
-
-unsigned char cardh[4] = { 0x00, 0x00, 0x5a, 0x5d };
-
-// Transfer Ready and the Buffer is Empty
-// static unsigned short StatReg = 0x002b;
-static unsigned short StatReg = TX_RDY | TX_EMPTY;
-static unsigned short ModeReg;
-static unsigned short CtrlReg;
-static unsigned short BaudReg;
-
-static unsigned int bufcount;
-static unsigned int parp;
-static unsigned int mcdst, rdwr;
-static unsigned char adrH, adrL;
-static unsigned int padst;
-static unsigned int gsdonglest;
-
-char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE];
-
-
-#define DONGLE_SIZE 0x40 * 0x1000
-
-unsigned int DongleBank;
-unsigned char DongleData[ DONGLE_SIZE ];
-static int DongleInit;
-
-
-#if 0
-// Breaks Twisted Metal 2 intro
-#define SIO_INT(eCycle) { \
- if (!Config.Sio) { \
- psxRegs.interrupt |= (1 << PSXINT_SIO); \
- psxRegs.intCycle[PSXINT_SIO].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_SIO].sCycle = psxRegs.cycle; \
- } \
- \
- StatReg &= ~RX_RDY; \
- StatReg &= ~TX_RDY; \
-}
-#endif
-
-#define SIO_INT(eCycle) { \
- if (!Config.Sio) { \
- psxRegs.interrupt |= (1 << PSXINT_SIO); \
- psxRegs.intCycle[PSXINT_SIO].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_SIO].sCycle = psxRegs.cycle; \
- } \
-}
-
-
-// clk cycle byte
-// 4us * 8bits = (PSXCLK / 1000000) * 32; (linuzappz)
-// TODO: add SioModePrescaler
-#define SIO_CYCLES (BaudReg * 8)
-
-// rely on this for now - someone's actual testing
-//#define SIO_CYCLES (PSXCLK / 57600)
-//PCSX 1.9.91
-//#define SIO_CYCLES 200
-//PCSX 1.9.91
-//#define SIO_CYCLES 270
-// ePSXe 1.6.0
-//#define SIO_CYCLES 535
-// ePSXe 1.7.0
-//#define SIO_CYCLES 635
-
-unsigned char reverse_8( unsigned char bits )
-{
- unsigned char tmp;
- int lcv;
-
- tmp = 0;
- for( lcv = 0; lcv < 8; lcv++ )
- {
- tmp >>= 1;
- tmp |= (bits & 0x80);
-
- bits <<= 1;
- }
-
- return tmp;
-}
-
-
-void sioWrite8(unsigned char value) {
-#ifdef PAD_LOG
- PAD_LOG("sio write8 %x\n", value);
-#endif
- switch (padst) {
- case 1: SIO_INT(SIO_CYCLES);
- /*
- $41-4F
- $41 = Find bits in poll respones
- $42 = Polling command
- $43 = Config mode (Dual shock?)
- $44 = Digital / Analog (after $F3)
- $45 = Get status info (Dual shock?)
-
- ID:
- $41 = Digital
- $73 = Analogue Red LED
- $53 = Analogue Green LED
-
- $23 = NegCon
- $12 = Mouse
- */
-
- if ((value & 0x40) == 0x40) {
- padst = 2; parp = 1;
- if (!Config.UseNet) {
- switch (CtrlReg & 0x2002) {
- case 0x0002:
- buf[parp] = PAD1_poll(value);
- break;
- case 0x2002:
- buf[parp] = PAD2_poll(value);
- break;
- }
- }/* else {
-// SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]);
- }*/
-
- if (!(buf[parp] & 0x0f)) {
- bufcount = 2 + 32;
- } else {
- bufcount = 2 + (buf[parp] & 0x0f) * 2;
- }
-
-
- // Digital / Dual Shock Controller
- if (buf[parp] == 0x41) {
- switch (value) {
- // enter config mode
- case 0x43:
- buf[1] = 0x43;
- break;
-
- // get status
- case 0x45:
- buf[1] = 0xf3;
- break;
- }
- }
-
-
- // NegCon - Wipeout 3
- if( buf[parp] == 0x23 ) {
- switch (value) {
- // enter config mode
- case 0x43:
- buf[1] = 0x79;
- break;
-
- // get status
- case 0x45:
- buf[1] = 0xf3;
- break;
- }
- }
- }
- else padst = 0;
- return;
- case 2:
- parp++;
-/* if (buf[1] == 0x45) {
- buf[parp] = 0;
- SIO_INT(SIO_CYCLES);
- return;
- }*/
- if (!Config.UseNet) {
- switch (CtrlReg & 0x2002) {
- case 0x0002: buf[parp] = PAD1_poll(value); break;
- case 0x2002: buf[parp] = PAD2_poll(value); break;
- }
- }
-
- if (parp == bufcount) { padst = 0; return; }
- SIO_INT(SIO_CYCLES);
- return;
- }
-
- switch (mcdst) {
- case 1:
- SIO_INT(SIO_CYCLES);
- if (rdwr) { parp++; return; }
- parp = 1;
- switch (value) {
- case 0x52: rdwr = 1; break;
- case 0x57: rdwr = 2; break;
- default: mcdst = 0;
- }
- return;
- case 2: // address H
- SIO_INT(SIO_CYCLES);
- adrH = value;
- *buf = 0;
- parp = 0;
- bufcount = 1;
- mcdst = 3;
- return;
- case 3: // address L
- SIO_INT(SIO_CYCLES);
- adrL = value;
- *buf = adrH;
- parp = 0;
- bufcount = 1;
- mcdst = 4;
- return;
- case 4:
- SIO_INT(SIO_CYCLES);
- parp = 0;
- switch (rdwr) {
- case 1: // read
- buf[0] = 0x5c;
- buf[1] = 0x5d;
- buf[2] = adrH;
- buf[3] = adrL;
- switch (CtrlReg & 0x2002) {
- case 0x0002:
- memcpy(&buf[4], Mcd1Data + (adrL | (adrH << 8)) * 128, 128);
- break;
- case 0x2002:
- memcpy(&buf[4], Mcd2Data + (adrL | (adrH << 8)) * 128, 128);
- break;
- }
- {
- char xor = 0;
- int i;
- for (i = 2; i < 128 + 4; i++)
- xor ^= buf[i];
- buf[132] = xor;
- }
- buf[133] = 0x47;
- bufcount = 133;
- break;
- case 2: // write
- buf[0] = adrL;
- buf[1] = value;
- buf[129] = 0x5c;
- buf[130] = 0x5d;
- buf[131] = 0x47;
- bufcount = 131;
- break;
- }
- mcdst = 5;
- return;
- case 5:
- parp++;
- if (rdwr == 2) {
- if (parp < 128) buf[parp + 1] = value;
- }
- SIO_INT(SIO_CYCLES);
- return;
- }
-
-
- /*
- GameShark CDX
-
- ae - be - ef - 04 + [00]
- ae - be - ef - 01 + 00 + [00] * $1000
- ae - be - ef - 01 + 42 + [00] * $1000
- ae - be - ef - 03 + 01,01,1f,e3,85,ae,d1,28 + [00] * 4
- */
- switch (gsdonglest) {
- // main command loop
- case 1:
- SIO_INT( SIO_CYCLES );
-
- // GS CDX
- // - unknown output
-
- // reset device when fail?
- if( value == 0xae )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
- }
-
-
- // GS CDX
- else if( value == 0xbe )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
-
-
- buf[0] = reverse_8( 0xde );
- }
-
-
- // GS CDX
- else if( value == 0xef )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
-
-
- buf[0] = reverse_8( 0xad );
- }
-
-
- // GS CDX [1 in + $1000 out + $1 out]
- else if( value == 0x01 )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
-
-
- // $00 = 0000 0000
- // - (reverse) 0000 0000
- buf[0] = 0x00;
- gsdonglest = 2;
- }
-
-
- // GS CDX [1 in + $1000 in + $1 out]
- else if( value == 0x02 )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
-
-
- // $00 = 0000 0000
- // - (reverse) 0000 0000
- buf[0] = 0x00;
- gsdonglest = 3;
- }
-
-
- // GS CDX [8 in, 4 out]
- else if( value == 0x03 )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
-
- // $00 = 0000 0000
- // - (reverse) 0000 0000
- buf[0] = 0x00;
-
- gsdonglest = 4;
- }
-
-
- // GS CDX [out 1]
- else if( value == 0x04 )
- {
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
-
-
- // $00 = 0000 0000
- // - (reverse) 0000 0000
- buf[0] = 0x00;
- gsdonglest = 5;
- }
- else
- {
- // ERROR!!
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
- buf[0] = 0xff;
-
- gsdonglest = 0;
- }
-
- return;
-
-
- // be - ef - 01
- case 2: {
- unsigned char checksum;
- unsigned int lcv;
-
- SIO_INT( SIO_CYCLES );
- StatReg |= RX_RDY;
-
-
- // read 1 byte
- DongleBank = buf[ 0 ];
-
-
- // write data + checksum
- checksum = 0;
- for( lcv = 0; lcv < 0x1000; lcv++ )
- {
- unsigned char data;
-
- data = DongleData[ DongleBank * 0x1000 + lcv ];
-
- buf[ lcv+1 ] = reverse_8( data );
- checksum += data;
- }
-
-
- parp = 0;
- bufcount = 0x1001;
- buf[ 0x1001 ] = reverse_8( checksum );
-
-
- gsdonglest = 255;
- return;
- }
-
-
- // be - ef - 02
- case 3:
- SIO_INT( SIO_CYCLES );
- StatReg |= RX_RDY;
-
- // command start
- if( parp < 0x1000+1 )
- {
- // read 1 byte
- buf[ parp ] = value;
- parp++;
- }
-
- if( parp == 0x1001 )
- {
- unsigned char checksum;
- unsigned int lcv;
-
- DongleBank = buf[0];
- memcpy( DongleData + DongleBank * 0x1000, buf+1, 0x1000 );
-
- // save to file
- SaveDongle( "memcards/CDX_Dongle.bin" );
-
-
- // write 8-bit checksum
- checksum = 0;
- for( lcv = 1; lcv < 0x1001; lcv++ )
- {
- checksum += buf[ lcv ];
- }
-
- parp = 0;
- bufcount = 1;
- buf[1] = reverse_8( checksum );
-
-
- // flush result
- gsdonglest = 255;
- }
- return;
-
-
- // be - ef - 03
- case 4:
- SIO_INT( SIO_CYCLES );
- StatReg |= RX_RDY;
-
- // command start
- if( parp < 8 )
- {
- // read 2 (?,?) + 4 (DATA?) + 2 (CRC?)
- buf[ parp ] = value;
- parp++;
- }
-
- if( parp == 8 )
- {
- // now write 4 bytes via -FOUR- $00 writes
- parp = 8;
- bufcount = 12;
-
-
- // TODO: Solve CDX algorithm
-
-
- // GS CDX [magic key]
- if( buf[2] == 0x12 && buf[3] == 0x34 &&
- buf[4] == 0x56 && buf[5] == 0x78 )
- {
- buf[9] = reverse_8( 0x3e );
- buf[10] = reverse_8( 0xa0 );
- buf[11] = reverse_8( 0x40 );
- buf[12] = reverse_8( 0x29 );
- }
-
- // GS CDX [address key #2 = 6ec]
- else if( buf[2] == 0x1f && buf[3] == 0xe3 &&
- buf[4] == 0x45 && buf[5] == 0x60 )
- {
- buf[9] = reverse_8( 0xee );
- buf[10] = reverse_8( 0xdd );
- buf[11] = reverse_8( 0x71 );
- buf[12] = reverse_8( 0xa8 );
- }
-
- // GS CDX [address key #3 = ???]
- else if( buf[2] == 0x1f && buf[3] == 0xe3 &&
- buf[4] == 0x72 && buf[5] == 0xe3 )
- {
- // unsolved!!
-
- // Used here: 80090348 / 80090498
-
- // dummy value - MSB
- buf[9] = reverse_8( 0xfa );
- buf[10] = reverse_8( 0xde );
- buf[11] = reverse_8( 0x21 );
- buf[12] = reverse_8( 0x97 );
- }
-
- // GS CDX [address key #4 = a00]
- else if( buf[2] == 0x1f && buf[3] == 0xe3 &&
- buf[4] == 0x85 && buf[5] == 0xae )
- {
- buf[9] = reverse_8( 0xee );
- buf[10] = reverse_8( 0xdd );
- buf[11] = reverse_8( 0x7d );
- buf[12] = reverse_8( 0x44 );
- }
-
- // GS CDX [address key #5 = 9ec]
- else if( buf[2] == 0x17 && buf[3] == 0xe3 &&
- buf[4] == 0xb5 && buf[5] == 0x60 )
- {
- buf[9] = reverse_8( 0xee );
- buf[10] = reverse_8( 0xdd );
- buf[11] = reverse_8( 0x7e );
- buf[12] = reverse_8( 0xa8 );
- }
-
- else
- {
- // dummy value - MSB
- buf[9] = reverse_8( 0xfa );
- buf[10] = reverse_8( 0xde );
- buf[11] = reverse_8( 0x21 );
- buf[12] = reverse_8( 0x97 );
- }
-
- // flush bytes -> done
- gsdonglest = 255;
- }
- return;
-
-
- // be - ef - 04
- case 5:
- if( value == 0x00 )
- {
- SIO_INT( SIO_CYCLES );
- StatReg |= RX_RDY;
-
-
- // read 1 byte
- parp = 0;
- bufcount = parp;
-
- // size of dongle card?
- buf[ 0 ] = reverse_8( DONGLE_SIZE / 0x1000 );
-
-
- // done already
- gsdonglest = 0;
- }
- return;
-
-
- // flush bytes -> done
- case 255:
- if( value == 0x00 )
- {
- //SIO_INT( SIO_CYCLES );
- SIO_INT(1);
- StatReg |= RX_RDY;
-
- parp++;
- if( parp == bufcount )
- {
- gsdonglest = 0;
-
-#ifdef GSDONGLE_LOG
- PAD_LOG("(gameshark dongle) DONE!!\n" );
-#endif
- }
- }
- else
- {
- // ERROR!!
- StatReg |= RX_RDY;
-
- parp = 0;
- bufcount = parp;
- buf[0] = 0xff;
-
- gsdonglest = 0;
- }
- return;
- }
-
-
- switch (value) {
- case 0x01: // start pad
- StatReg |= RX_RDY; // Transfer is Ready
-
- if (!Config.UseNet) {
- switch (CtrlReg & 0x2002) {
- case 0x0002: buf[0] = PAD1_startPoll(1); break;
- case 0x2002: buf[0] = PAD2_startPoll(2); break;
- }
- } else {
- if ((CtrlReg & 0x2002) == 0x0002) {
- int i, j;
-
- PAD1_startPoll(1);
- buf[0] = 0;
- buf[1] = PAD1_poll(0x42);
- if (!(buf[1] & 0x0f)) {
- bufcount = 32;
- } else {
- bufcount = (buf[1] & 0x0f) * 2;
- }
- buf[2] = PAD1_poll(0);
- i = 3;
- j = bufcount;
- while (j--) {
- buf[i++] = PAD1_poll(0);
- }
- bufcount+= 3;
-
- if (NET_sendPadData(buf, bufcount) == -1)
- netError();
-
- if (NET_recvPadData(buf, 1) == -1)
- netError();
- if (NET_recvPadData(buf + 128, 2) == -1)
- netError();
- } else {
- memcpy(buf, buf + 128, 32);
- }
- }
-
- bufcount = 2;
- parp = 0;
- padst = 1;
- SIO_INT(SIO_CYCLES);
- return;
- case 0x81: // start memcard
- StatReg |= RX_RDY;
-#if 0
- // Chronicles of the Sword - no memcard = password options
- if( Config.Memcard == 1 ) return;
-#endif
- memcpy(buf, cardh, 4);
- parp = 0;
- bufcount = 3;
- mcdst = 1;
- rdwr = 0;
- SIO_INT(SIO_CYCLES);
- return;
-
- case 0xae: // GameShark CDX - start dongle
- StatReg |= RX_RDY;
- gsdonglest = 1;
-
- parp = 0;
- bufcount = parp;
-
- if( !DongleInit )
- {
- LoadDongle( "memcards/CDX_Dongle.bin" );
-
- DongleInit = 1;
- }
-
- SIO_INT( SIO_CYCLES );
- return;
-
- default: // no hardware found
- StatReg |= RX_RDY;
- return;
- }
-}
-
-void sioWriteStat16(unsigned short value) {
-}
-
-void sioWriteMode16(unsigned short value) {
- ModeReg = value;
-}
-
-void sioWriteCtrl16(unsigned short value) {
- CtrlReg = value & ~RESET_ERR;
- if (value & RESET_ERR) StatReg &= ~IRQ;
- if ((CtrlReg & SIO_RESET) || (!CtrlReg)) {
- padst = 0; mcdst = 0; parp = 0;
- StatReg = TX_RDY | TX_EMPTY;
- psxRegs.interrupt &= ~(1 << PSXINT_SIO);
- }
-}
-
-void sioWriteBaud16(unsigned short value) {
- BaudReg = value;
-}
-
-unsigned char sioRead8() {
- unsigned char ret = 0;
-
- if ((StatReg & RX_RDY)/* && (CtrlReg & RX_PERM)*/) {
-// StatReg &= ~RX_OVERRUN;
- ret = buf[parp];
- if (parp == bufcount) {
- StatReg &= ~RX_RDY; // Receive is not Ready now
- if (mcdst == 5) {
- mcdst = 0;
- if (rdwr == 2) {
- switch (CtrlReg & 0x2002) {
- case 0x0002:
- memcpy(Mcd1Data + (adrL | (adrH << 8)) * 128, &buf[1], 128);
- SaveMcd(Config.Mcd1, Mcd1Data, (adrL | (adrH << 8)) * 128, 128);
- break;
- case 0x2002:
- memcpy(Mcd2Data + (adrL | (adrH << 8)) * 128, &buf[1], 128);
- SaveMcd(Config.Mcd2, Mcd2Data, (adrL | (adrH << 8)) * 128, 128);
- break;
- }
- }
- }
- if (padst == 2) padst = 0;
- if (mcdst == 1) {
- mcdst = 2;
- StatReg|= RX_RDY;
- }
- }
- }
-
-#ifdef PAD_LOG
- PAD_LOG("sio read8 ;ret = %x\n", ret);
-#endif
- return ret;
-}
-
-unsigned short sioReadStat16() {
- u16 hard;
-
- hard = StatReg;
-
-#if 0
- // wait for IRQ first
- if( psxRegs.interrupt & (1 << PSXINT_SIO) )
- {
- hard &= ~TX_RDY;
- hard &= ~RX_RDY;
- hard &= ~TX_EMPTY;
- }
-#endif
-
- return hard;
-}
-
-unsigned short sioReadMode16() {
- return ModeReg;
-}
-
-unsigned short sioReadCtrl16() {
- return CtrlReg;
-}
-
-unsigned short sioReadBaud16() {
- return BaudReg;
-}
-
-void netError() {
- ClosePlugins();
- SysMessage(_("Connection closed!\n"));
-
- CdromId[0] = '\0';
- CdromLabel[0] = '\0';
-
- SysRunGui();
-}
-
-void sioInterrupt() {
-#ifdef PAD_LOG
- PAD_LOG("Sio Interrupt (CP0.Status = %x)\n", psxRegs.CP0.n.Status);
-#endif
-// SysPrintf("Sio Interrupt\n");
- StatReg |= IRQ;
- psxHu32ref(0x1070) |= SWAPu32(0x80);
-
-#if 0
- // Rhapsody: fixes input problems
- // Twisted Metal 2: breaks intro
- StatReg |= TX_RDY;
- StatReg |= RX_RDY;
-#endif
-}
-
-void LoadMcd(int mcd, char *str) {
- FILE *f;
- char *data = NULL;
-
- if (mcd == 1) data = Mcd1Data;
- if (mcd == 2) data = Mcd2Data;
-
- if (*str == 0) {
- sprintf(str, "memcards/card%d.mcd", mcd);
- SysPrintf(_("No memory card value was specified - creating a default card %s\n"), str);
- }
- f = fopen(str, "rb");
- if (f == NULL) {
- SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str);
- CreateMcd(str);
- f = fopen(str, "rb");
- if (f != NULL) {
- struct stat buf;
-
- if (stat(str, &buf) != -1) {
- if (buf.st_size == MCD_SIZE + 64)
- fseek(f, 64, SEEK_SET);
- else if(buf.st_size == MCD_SIZE + 3904)
- fseek(f, 3904, SEEK_SET);
- }
- fread(data, 1, MCD_SIZE, f);
- fclose(f);
- }
- else
- SysMessage(_("Memory card %s failed to load!\n"), str);
- }
- else {
- struct stat buf;
- SysPrintf(_("Loading memory card %s\n"), str);
- if (stat(str, &buf) != -1) {
- if (buf.st_size == MCD_SIZE + 64)
- fseek(f, 64, SEEK_SET);
- else if(buf.st_size == MCD_SIZE + 3904)
- fseek(f, 3904, SEEK_SET);
- }
- fread(data, 1, MCD_SIZE, f);
- fclose(f);
- }
-}
-
-void LoadMcds(char *mcd1, char *mcd2) {
- LoadMcd(1, mcd1);
- LoadMcd(2, mcd2);
-}
-
-void SaveMcd(char *mcd, char *data, uint32_t adr, int size) {
- FILE *f;
-
- f = fopen(mcd, "r+b");
- if (f != NULL) {
- struct stat buf;
-
- if (stat(mcd, &buf) != -1) {
- if (buf.st_size == MCD_SIZE + 64)
- fseek(f, adr + 64, SEEK_SET);
- else if (buf.st_size == MCD_SIZE + 3904)
- fseek(f, adr + 3904, SEEK_SET);
- else
- fseek(f, adr, SEEK_SET);
- } else
- fseek(f, adr, SEEK_SET);
-
- fwrite(data + adr, 1, size, f);
- fclose(f);
- return;
- }
-
-#if 0
- // try to create it again if we can't open it
- f = fopen(mcd, "wb");
- if (f != NULL) {
- fwrite(data, 1, MCD_SIZE, f);
- fclose(f);
- }
-#endif
-
- ConvertMcd(mcd, data);
-}
-
-void CreateMcd(char *mcd) {
- FILE *f;
- struct stat buf;
- int s = MCD_SIZE;
- int i = 0, j;
-
- f = fopen(mcd, "wb");
- if (f == NULL)
- return;
-
- if (stat(mcd, &buf) != -1) {
- if ((buf.st_size == MCD_SIZE + 3904) || strstr(mcd, ".gme")) {
- s = s + 3904;
- fputc('1', f);
- s--;
- fputc('2', f);
- s--;
- fputc('3', f);
- s--;
- fputc('-', f);
- s--;
- fputc('4', f);
- s--;
- fputc('5', f);
- s--;
- fputc('6', f);
- s--;
- fputc('-', f);
- s--;
- fputc('S', f);
- s--;
- fputc('T', f);
- s--;
- fputc('D', f);
- s--;
- for (i = 0; i < 7; i++) {
- fputc(0, f);
- s--;
- }
- fputc(1, f);
- s--;
- fputc(0, f);
- s--;
- fputc(1, f);
- s--;
- fputc('M', f);
- s--;
- fputc('Q', f);
- s--;
- for (i = 0; i < 14; i++) {
- fputc(0xa0, f);
- s--;
- }
- fputc(0, f);
- s--;
- fputc(0xff, f);
- while (s-- > (MCD_SIZE + 1))
- fputc(0, f);
- } else if ((buf.st_size == MCD_SIZE + 64) || strstr(mcd, ".mem") || strstr(mcd, ".vgs")) {
- s = s + 64;
- fputc('V', f);
- s--;
- fputc('g', f);
- s--;
- fputc('s', f);
- s--;
- fputc('M', f);
- s--;
- for (i = 0; i < 3; i++) {
- fputc(1, f);
- s--;
- fputc(0, f);
- s--;
- fputc(0, f);
- s--;
- fputc(0, f);
- s--;
- }
- fputc(0, f);
- s--;
- fputc(2, f);
- while (s-- > (MCD_SIZE + 1))
- fputc(0, f);
- }
- }
- fputc('M', f);
- s--;
- fputc('C', f);
- s--;
- while (s-- > (MCD_SIZE - 127))
- fputc(0, f);
- fputc(0xe, f);
- s--;
-
- for (i = 0; i < 15; i++) { // 15 blocks
- fputc(0xa0, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0xff, f);
- s--;
- fputc(0xff, f);
- s--;
- for (j = 0; j < 117; j++) {
- fputc(0x00, f);
- s--;
- }
- fputc(0xa0, f);
- s--;
- }
-
- for (i = 0; i < 20; i++) {
- fputc(0xff, f);
- s--;
- fputc(0xff, f);
- s--;
- fputc(0xff, f);
- s--;
- fputc(0xff, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0x00, f);
- s--;
- fputc(0xff, f);
- s--;
- fputc(0xff, f);
- s--;
- for (j = 0; j < 118; j++) {
- fputc(0x00, f);
- s--;
- }
- }
-
- while ((s--) >= 0)
- fputc(0, f);
-
- fclose(f);
-}
-
-void ConvertMcd(char *mcd, char *data) {
- FILE *f;
- int i = 0;
- int s = MCD_SIZE;
-
- if (strstr(mcd, ".gme")) {
- f = fopen(mcd, "wb");
- if (f != NULL) {
- fwrite(data - 3904, 1, MCD_SIZE + 3904, f);
- fclose(f);
- }
- f = fopen(mcd, "r+");
- s = s + 3904;
- fputc('1', f); s--;
- fputc('2', f); s--;
- fputc('3', f); s--;
- fputc('-', f); s--;
- fputc('4', f); s--;
- fputc('5', f); s--;
- fputc('6', f); s--;
- fputc('-', f); s--;
- fputc('S', f); s--;
- fputc('T', f); s--;
- fputc('D', f); s--;
- for (i = 0; i < 7; i++) {
- fputc(0, f); s--;
- }
- fputc(1, f); s--;
- fputc(0, f); s--;
- fputc(1, f); s--;
- fputc('M', f); s--;
- fputc('Q', f); s--;
- for(i=0;i<14;i++) {
- fputc(0xa0, f); s--;
- }
- fputc(0, f); s--;
- fputc(0xff, f);
- while (s-- > (MCD_SIZE+1)) fputc(0, f);
- fclose(f);
- } else if(strstr(mcd, ".mem") || strstr(mcd,".vgs")) {
- f = fopen(mcd, "wb");
- if (f != NULL) {
- fwrite(data-64, 1, MCD_SIZE+64, f);
- fclose(f);
- }
- f = fopen(mcd, "r+");
- s = s + 64;
- fputc('V', f); s--;
- fputc('g', f); s--;
- fputc('s', f); s--;
- fputc('M', f); s--;
- for(i=0;i<3;i++) {
- fputc(1, f); s--;
- fputc(0, f); s--;
- fputc(0, f); s--;
- fputc(0, f); s--;
- }
- fputc(0, f); s--;
- fputc(2, f);
- while (s-- > (MCD_SIZE+1)) fputc(0, f);
- fclose(f);
- } else {
- f = fopen(mcd, "wb");
- if (f != NULL) {
- fwrite(data, 1, MCD_SIZE, f);
- fclose(f);
- }
- }
-}
-
-void GetMcdBlockInfo(int mcd, int block, McdBlock *Info) {
- unsigned char *data = NULL, *ptr, *str, *sstr;
- unsigned short clut[16];
- unsigned short c;
- int i, x;
-
- memset(Info, 0, sizeof(McdBlock));
-
- if (mcd == 1) data = Mcd1Data;
- if (mcd == 2) data = Mcd2Data;
-
- ptr = data + block * 8192 + 2;
-
- Info->IconCount = *ptr & 0x3;
-
- ptr += 2;
-
- x = 0;
-
- str = Info->Title;
- sstr = Info->sTitle;
-
- for (i = 0; i < 48; i++) {
- c = *(ptr) << 8;
- c |= *(ptr + 1);
- if (!c) break;
-
- // Convert ASCII characters to half-width
- if (c >= 0x8281 && c <= 0x829A)
- c = (c - 0x8281) + 'a';
- else if (c >= 0x824F && c <= 0x827A)
- c = (c - 0x824F) + '0';
- else if (c == 0x8140) c = ' ';
- else if (c == 0x8143) c = ',';
- else if (c == 0x8144) c = '.';
- else if (c == 0x8146) c = ':';
- else if (c == 0x8147) c = ';';
- else if (c == 0x8148) c = '?';
- else if (c == 0x8149) c = '!';
- else if (c == 0x815E) c = '/';
- else if (c == 0x8168) c = '"';
- else if (c == 0x8169) c = '(';
- else if (c == 0x816A) c = ')';
- else if (c == 0x816D) c = '[';
- else if (c == 0x816E) c = ']';
- else if (c == 0x817C) c = '-';
- else {
- str[i] = ' ';
- sstr[x++] = *ptr++; sstr[x++] = *ptr++;
- continue;
- }
-
- str[i] = sstr[x++] = c;
- ptr += 2;
- }
-
- trim(str);
- trim(sstr);
-
- ptr = data + block * 8192 + 0x60; // icon palette data
-
- for (i = 0; i < 16; i++) {
- clut[i] = *((unsigned short *)ptr);
- ptr += 2;
- }
-
- for (i = 0; i < Info->IconCount; i++) {
- short *icon = &Info->Icon[i * 16 * 16];
-
- ptr = data + block * 8192 + 128 + 128 * i; // icon data
-
- for (x = 0; x < 16 * 16; x++) {
- icon[x++] = clut[*ptr & 0xf];
- icon[x] = clut[*ptr >> 4];
- ptr++;
- }
- }
-
- ptr = data + block * 128;
-
- Info->Flags = *ptr;
-
- ptr += 0xa;
- strncpy(Info->ID, ptr, 12);
- ptr += 12;
- strncpy(Info->Name, ptr, 16);
-}
-
-int sioFreeze(gzFile f, int Mode) {
- gzfreeze(buf, sizeof(buf));
- gzfreeze(&StatReg, sizeof(StatReg));
- gzfreeze(&ModeReg, sizeof(ModeReg));
- gzfreeze(&CtrlReg, sizeof(CtrlReg));
- gzfreeze(&BaudReg, sizeof(BaudReg));
- gzfreeze(&bufcount, sizeof(bufcount));
- gzfreeze(&parp, sizeof(parp));
- gzfreeze(&mcdst, sizeof(mcdst));
- gzfreeze(&rdwr, sizeof(rdwr));
- gzfreeze(&adrH, sizeof(adrH));
- gzfreeze(&adrL, sizeof(adrL));
- gzfreeze(&padst, sizeof(padst));
-
- return 0;
-}
-
-
-void LoadDongle( char *str )
-{
- FILE *f;
-
- f = fopen(str, "r+b");
- if (f != NULL) {
- fread( DongleData, 1, DONGLE_SIZE, f );
- fclose( f );
- }
- else {
- u32 *ptr, lcv;
-
- ptr = (unsigned int *) DongleData;
-
- // create temp data
- ptr[0] = (u32) 0x02015447;
- ptr[1] = (u32) 7;
- ptr[2] = (u32) 1;
- ptr[3] = (u32) 0;
-
- for( lcv=4; lcv<0x6c / 4; lcv++ )
- {
- ptr[ lcv ] = 0;
- }
-
- ptr[ lcv ] = (u32) 0x02000100;
- lcv++;
-
- while( lcv < 0x1000/4 )
- {
- ptr[ lcv ] = (u32) 0xffffffff;
- lcv++;
- }
- }
-}
-
-void SaveDongle( char *str )
-{
- FILE *f;
-
- f = fopen(str, "wb");
- if (f != NULL) {
- fwrite( DongleData, 1, DONGLE_SIZE, f );
- fclose( f );
- }
-}
+/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +/* +* SIO functions. +*/ + +#include "sio.h" +#include <sys/stat.h> + +// 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 + +// *** FOR WORKS ON PADS AND MEMORY CARDS ***** + + +void LoadDongle( char *str ); +void SaveDongle( char *str ); + + +#define BUFFER_SIZE 0x1010 + +static unsigned char buf[ BUFFER_SIZE ]; + +unsigned char cardh[4] = { 0x00, 0x00, 0x5a, 0x5d }; + +// Transfer Ready and the Buffer is Empty +// static unsigned short StatReg = 0x002b; +static unsigned short StatReg = TX_RDY | TX_EMPTY; +static unsigned short ModeReg; +static unsigned short CtrlReg; +static unsigned short BaudReg; + +static unsigned int bufcount; +static unsigned int parp; +static unsigned int mcdst, rdwr; +static unsigned char adrH, adrL; +static unsigned int padst; +static unsigned int gsdonglest; + +char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE]; + + +#define DONGLE_SIZE 0x40 * 0x1000 + +unsigned int DongleBank; +unsigned char DongleData[ DONGLE_SIZE ]; +static int DongleInit; + + +#if 0 +// Breaks Twisted Metal 2 intro +#define SIO_INT(eCycle) { \ + if (!Config.Sio) { \ + psxRegs.interrupt |= (1 << PSXINT_SIO); \ + psxRegs.intCycle[PSXINT_SIO].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_SIO].sCycle = psxRegs.cycle; \ + } \ + \ + StatReg &= ~RX_RDY; \ + StatReg &= ~TX_RDY; \ +} +#endif + +#define SIO_INT(eCycle) { \ + if (!Config.Sio) { \ + psxRegs.interrupt |= (1 << PSXINT_SIO); \ + psxRegs.intCycle[PSXINT_SIO].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_SIO].sCycle = psxRegs.cycle; \ + } \ +} + + +// clk cycle byte +// 4us * 8bits = (PSXCLK / 1000000) * 32; (linuzappz) +// TODO: add SioModePrescaler +#define SIO_CYCLES (BaudReg * 8) + +// rely on this for now - someone's actual testing +//#define SIO_CYCLES (PSXCLK / 57600) +//PCSX 1.9.91 +//#define SIO_CYCLES 200 +//PCSX 1.9.91 +//#define SIO_CYCLES 270 +// ePSXe 1.6.0 +//#define SIO_CYCLES 535 +// ePSXe 1.7.0 +//#define SIO_CYCLES 635 + +unsigned char reverse_8( unsigned char bits ) +{ + unsigned char tmp; + int lcv; + + tmp = 0; + for( lcv = 0; lcv < 8; lcv++ ) + { + tmp >>= 1; + tmp |= (bits & 0x80); + + bits <<= 1; + } + + return tmp; +} + + +void sioWrite8(unsigned char value) { +#ifdef PAD_LOG + PAD_LOG("sio write8 %x\n", value); +#endif + switch (padst) { + case 1: SIO_INT(SIO_CYCLES); + /* + $41-4F + $41 = Find bits in poll respones + $42 = Polling command + $43 = Config mode (Dual shock?) + $44 = Digital / Analog (after $F3) + $45 = Get status info (Dual shock?) + + ID: + $41 = Digital + $73 = Analogue Red LED + $53 = Analogue Green LED + + $23 = NegCon + $12 = Mouse + */ + + if ((value & 0x40) == 0x40) { + padst = 2; parp = 1; + if (!Config.UseNet) { + switch (CtrlReg & 0x2002) { + case 0x0002: + buf[parp] = PAD1_poll(value); + break; + case 0x2002: + buf[parp] = PAD2_poll(value); + break; + } + }/* else { +// SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]); + }*/ + + if (!(buf[parp] & 0x0f)) { + bufcount = 2 + 32; + } else { + bufcount = 2 + (buf[parp] & 0x0f) * 2; + } + + + // Digital / Dual Shock Controller + if (buf[parp] == 0x41) { + switch (value) { + // enter config mode + case 0x43: + buf[1] = 0x43; + break; + + // get status + case 0x45: + buf[1] = 0xf3; + break; + } + } + + + // NegCon - Wipeout 3 + if( buf[parp] == 0x23 ) { + switch (value) { + // enter config mode + case 0x43: + buf[1] = 0x79; + break; + + // get status + case 0x45: + buf[1] = 0xf3; + break; + } + } + } + else padst = 0; + return; + case 2: + parp++; +/* if (buf[1] == 0x45) { + buf[parp] = 0; + SIO_INT(SIO_CYCLES); + return; + }*/ + if (!Config.UseNet) { + switch (CtrlReg & 0x2002) { + case 0x0002: buf[parp] = PAD1_poll(value); break; + case 0x2002: buf[parp] = PAD2_poll(value); break; + } + } + + if (parp == bufcount) { padst = 0; return; } + SIO_INT(SIO_CYCLES); + return; + } + + switch (mcdst) { + case 1: + SIO_INT(SIO_CYCLES); + if (rdwr) { parp++; return; } + parp = 1; + switch (value) { + case 0x52: rdwr = 1; break; + case 0x57: rdwr = 2; break; + default: mcdst = 0; + } + return; + case 2: // address H + SIO_INT(SIO_CYCLES); + adrH = value; + *buf = 0; + parp = 0; + bufcount = 1; + mcdst = 3; + return; + case 3: // address L + SIO_INT(SIO_CYCLES); + adrL = value; + *buf = adrH; + parp = 0; + bufcount = 1; + mcdst = 4; + return; + case 4: + SIO_INT(SIO_CYCLES); + parp = 0; + switch (rdwr) { + case 1: // read + buf[0] = 0x5c; + buf[1] = 0x5d; + buf[2] = adrH; + buf[3] = adrL; + switch (CtrlReg & 0x2002) { + case 0x0002: + memcpy(&buf[4], Mcd1Data + (adrL | (adrH << 8)) * 128, 128); + break; + case 0x2002: + memcpy(&buf[4], Mcd2Data + (adrL | (adrH << 8)) * 128, 128); + break; + } + { + char xor = 0; + int i; + for (i = 2; i < 128 + 4; i++) + xor ^= buf[i]; + buf[132] = xor; + } + buf[133] = 0x47; + bufcount = 133; + break; + case 2: // write + buf[0] = adrL; + buf[1] = value; + buf[129] = 0x5c; + buf[130] = 0x5d; + buf[131] = 0x47; + bufcount = 131; + break; + } + mcdst = 5; + return; + case 5: + parp++; + if (rdwr == 2) { + if (parp < 128) buf[parp + 1] = value; + } + SIO_INT(SIO_CYCLES); + return; + } + + + /* + GameShark CDX + + ae - be - ef - 04 + [00] + ae - be - ef - 01 + 00 + [00] * $1000 + ae - be - ef - 01 + 42 + [00] * $1000 + ae - be - ef - 03 + 01,01,1f,e3,85,ae,d1,28 + [00] * 4 + */ + switch (gsdonglest) { + // main command loop + case 1: + SIO_INT( SIO_CYCLES ); + + // GS CDX + // - unknown output + + // reset device when fail? + if( value == 0xae ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + } + + + // GS CDX + else if( value == 0xbe ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + + + buf[0] = reverse_8( 0xde ); + } + + + // GS CDX + else if( value == 0xef ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + + + buf[0] = reverse_8( 0xad ); + } + + + // GS CDX [1 in + $1000 out + $1 out] + else if( value == 0x01 ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + + + // $00 = 0000 0000 + // - (reverse) 0000 0000 + buf[0] = 0x00; + gsdonglest = 2; + } + + + // GS CDX [1 in + $1000 in + $1 out] + else if( value == 0x02 ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + + + // $00 = 0000 0000 + // - (reverse) 0000 0000 + buf[0] = 0x00; + gsdonglest = 3; + } + + + // GS CDX [8 in, 4 out] + else if( value == 0x03 ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + + // $00 = 0000 0000 + // - (reverse) 0000 0000 + buf[0] = 0x00; + + gsdonglest = 4; + } + + + // GS CDX [out 1] + else if( value == 0x04 ) + { + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + + + // $00 = 0000 0000 + // - (reverse) 0000 0000 + buf[0] = 0x00; + gsdonglest = 5; + } + else + { + // ERROR!! + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + buf[0] = 0xff; + + gsdonglest = 0; + } + + return; + + + // be - ef - 01 + case 2: { + unsigned char checksum; + unsigned int lcv; + + SIO_INT( SIO_CYCLES ); + StatReg |= RX_RDY; + + + // read 1 byte + DongleBank = buf[ 0 ]; + + + // write data + checksum + checksum = 0; + for( lcv = 0; lcv < 0x1000; lcv++ ) + { + unsigned char data; + + data = DongleData[ DongleBank * 0x1000 + lcv ]; + + buf[ lcv+1 ] = reverse_8( data ); + checksum += data; + } + + + parp = 0; + bufcount = 0x1001; + buf[ 0x1001 ] = reverse_8( checksum ); + + + gsdonglest = 255; + return; + } + + + // be - ef - 02 + case 3: + SIO_INT( SIO_CYCLES ); + StatReg |= RX_RDY; + + // command start + if( parp < 0x1000+1 ) + { + // read 1 byte + buf[ parp ] = value; + parp++; + } + + if( parp == 0x1001 ) + { + unsigned char checksum; + unsigned int lcv; + + DongleBank = buf[0]; + memcpy( DongleData + DongleBank * 0x1000, buf+1, 0x1000 ); + + // save to file + SaveDongle( "memcards/CDX_Dongle.bin" ); + + + // write 8-bit checksum + checksum = 0; + for( lcv = 1; lcv < 0x1001; lcv++ ) + { + checksum += buf[ lcv ]; + } + + parp = 0; + bufcount = 1; + buf[1] = reverse_8( checksum ); + + + // flush result + gsdonglest = 255; + } + return; + + + // be - ef - 03 + case 4: + SIO_INT( SIO_CYCLES ); + StatReg |= RX_RDY; + + // command start + if( parp < 8 ) + { + // read 2 (?,?) + 4 (DATA?) + 2 (CRC?) + buf[ parp ] = value; + parp++; + } + + if( parp == 8 ) + { + // now write 4 bytes via -FOUR- $00 writes + parp = 8; + bufcount = 12; + + + // TODO: Solve CDX algorithm + + + // GS CDX [magic key] + if( buf[2] == 0x12 && buf[3] == 0x34 && + buf[4] == 0x56 && buf[5] == 0x78 ) + { + buf[9] = reverse_8( 0x3e ); + buf[10] = reverse_8( 0xa0 ); + buf[11] = reverse_8( 0x40 ); + buf[12] = reverse_8( 0x29 ); + } + + // GS CDX [address key #2 = 6ec] + else if( buf[2] == 0x1f && buf[3] == 0xe3 && + buf[4] == 0x45 && buf[5] == 0x60 ) + { + buf[9] = reverse_8( 0xee ); + buf[10] = reverse_8( 0xdd ); + buf[11] = reverse_8( 0x71 ); + buf[12] = reverse_8( 0xa8 ); + } + + // GS CDX [address key #3 = ???] + else if( buf[2] == 0x1f && buf[3] == 0xe3 && + buf[4] == 0x72 && buf[5] == 0xe3 ) + { + // unsolved!! + + // Used here: 80090348 / 80090498 + + // dummy value - MSB + buf[9] = reverse_8( 0xfa ); + buf[10] = reverse_8( 0xde ); + buf[11] = reverse_8( 0x21 ); + buf[12] = reverse_8( 0x97 ); + } + + // GS CDX [address key #4 = a00] + else if( buf[2] == 0x1f && buf[3] == 0xe3 && + buf[4] == 0x85 && buf[5] == 0xae ) + { + buf[9] = reverse_8( 0xee ); + buf[10] = reverse_8( 0xdd ); + buf[11] = reverse_8( 0x7d ); + buf[12] = reverse_8( 0x44 ); + } + + // GS CDX [address key #5 = 9ec] + else if( buf[2] == 0x17 && buf[3] == 0xe3 && + buf[4] == 0xb5 && buf[5] == 0x60 ) + { + buf[9] = reverse_8( 0xee ); + buf[10] = reverse_8( 0xdd ); + buf[11] = reverse_8( 0x7e ); + buf[12] = reverse_8( 0xa8 ); + } + + else + { + // dummy value - MSB + buf[9] = reverse_8( 0xfa ); + buf[10] = reverse_8( 0xde ); + buf[11] = reverse_8( 0x21 ); + buf[12] = reverse_8( 0x97 ); + } + + // flush bytes -> done + gsdonglest = 255; + } + return; + + + // be - ef - 04 + case 5: + if( value == 0x00 ) + { + SIO_INT( SIO_CYCLES ); + StatReg |= RX_RDY; + + + // read 1 byte + parp = 0; + bufcount = parp; + + // size of dongle card? + buf[ 0 ] = reverse_8( DONGLE_SIZE / 0x1000 ); + + + // done already + gsdonglest = 0; + } + return; + + + // flush bytes -> done + case 255: + if( value == 0x00 ) + { + //SIO_INT( SIO_CYCLES ); + SIO_INT(1); + StatReg |= RX_RDY; + + parp++; + if( parp == bufcount ) + { + gsdonglest = 0; + +#ifdef GSDONGLE_LOG + PAD_LOG("(gameshark dongle) DONE!!\n" ); +#endif + } + } + else + { + // ERROR!! + StatReg |= RX_RDY; + + parp = 0; + bufcount = parp; + buf[0] = 0xff; + + gsdonglest = 0; + } + return; + } + + + switch (value) { + case 0x01: // start pad + StatReg |= RX_RDY; // Transfer is Ready + + if (!Config.UseNet) { + switch (CtrlReg & 0x2002) { + case 0x0002: buf[0] = PAD1_startPoll(1); break; + case 0x2002: buf[0] = PAD2_startPoll(2); break; + } + } else { + if ((CtrlReg & 0x2002) == 0x0002) { + int i, j; + + PAD1_startPoll(1); + buf[0] = 0; + buf[1] = PAD1_poll(0x42); + if (!(buf[1] & 0x0f)) { + bufcount = 32; + } else { + bufcount = (buf[1] & 0x0f) * 2; + } + buf[2] = PAD1_poll(0); + i = 3; + j = bufcount; + while (j--) { + buf[i++] = PAD1_poll(0); + } + bufcount+= 3; + + if (NET_sendPadData(buf, bufcount) == -1) + netError(); + + if (NET_recvPadData(buf, 1) == -1) + netError(); + if (NET_recvPadData(buf + 128, 2) == -1) + netError(); + } else { + memcpy(buf, buf + 128, 32); + } + } + + bufcount = 2; + parp = 0; + padst = 1; + SIO_INT(SIO_CYCLES); + return; + case 0x81: // start memcard + StatReg |= RX_RDY; +#if 0 + // Chronicles of the Sword - no memcard = password options + if( Config.Memcard == 1 ) return; +#endif + memcpy(buf, cardh, 4); + parp = 0; + bufcount = 3; + mcdst = 1; + rdwr = 0; + SIO_INT(SIO_CYCLES); + return; + + case 0xae: // GameShark CDX - start dongle + StatReg |= RX_RDY; + gsdonglest = 1; + + parp = 0; + bufcount = parp; + + if( !DongleInit ) + { + LoadDongle( "memcards/CDX_Dongle.bin" ); + + DongleInit = 1; + } + + SIO_INT( SIO_CYCLES ); + return; + + default: // no hardware found + StatReg |= RX_RDY; + return; + } +} + +void sioWriteStat16(unsigned short value) { +} + +void sioWriteMode16(unsigned short value) { + ModeReg = value; +} + +void sioWriteCtrl16(unsigned short value) { + CtrlReg = value & ~RESET_ERR; + if (value & RESET_ERR) StatReg &= ~IRQ; + if ((CtrlReg & SIO_RESET) || (!CtrlReg)) { + padst = 0; mcdst = 0; parp = 0; + StatReg = TX_RDY | TX_EMPTY; + psxRegs.interrupt &= ~(1 << PSXINT_SIO); + } +} + +void sioWriteBaud16(unsigned short value) { + BaudReg = value; +} + +unsigned char sioRead8() { + unsigned char ret = 0; + + if ((StatReg & RX_RDY)/* && (CtrlReg & RX_PERM)*/) { +// StatReg &= ~RX_OVERRUN; + ret = buf[parp]; + if (parp == bufcount) { + StatReg &= ~RX_RDY; // Receive is not Ready now + if (mcdst == 5) { + mcdst = 0; + if (rdwr == 2) { + switch (CtrlReg & 0x2002) { + case 0x0002: + memcpy(Mcd1Data + (adrL | (adrH << 8)) * 128, &buf[1], 128); + SaveMcd(Config.Mcd1, Mcd1Data, (adrL | (adrH << 8)) * 128, 128); + break; + case 0x2002: + memcpy(Mcd2Data + (adrL | (adrH << 8)) * 128, &buf[1], 128); + SaveMcd(Config.Mcd2, Mcd2Data, (adrL | (adrH << 8)) * 128, 128); + break; + } + } + } + if (padst == 2) padst = 0; + if (mcdst == 1) { + mcdst = 2; + StatReg|= RX_RDY; + } + } + } + +#ifdef PAD_LOG + PAD_LOG("sio read8 ;ret = %x\n", ret); +#endif + return ret; +} + +unsigned short sioReadStat16() { + u16 hard; + + hard = StatReg; + +#if 0 + // wait for IRQ first + if( psxRegs.interrupt & (1 << PSXINT_SIO) ) + { + hard &= ~TX_RDY; + hard &= ~RX_RDY; + hard &= ~TX_EMPTY; + } +#endif + + return hard; +} + +unsigned short sioReadMode16() { + return ModeReg; +} + +unsigned short sioReadCtrl16() { + return CtrlReg; +} + +unsigned short sioReadBaud16() { + return BaudReg; +} + +void netError() { + ClosePlugins(); + SysMessage(_("Connection closed!\n")); + + CdromId[0] = '\0'; + CdromLabel[0] = '\0'; + + SysRunGui(); +} + +void sioInterrupt() { +#ifdef PAD_LOG + PAD_LOG("Sio Interrupt (CP0.Status = %x)\n", psxRegs.CP0.n.Status); +#endif +// SysPrintf("Sio Interrupt\n"); + StatReg |= IRQ; + psxHu32ref(0x1070) |= SWAPu32(0x80); + +#if 0 + // Rhapsody: fixes input problems + // Twisted Metal 2: breaks intro + StatReg |= TX_RDY; + StatReg |= RX_RDY; +#endif +} + +void LoadMcd(int mcd, char *str) { + FILE *f; + char *data = NULL; + + if (mcd == 1) data = Mcd1Data; + if (mcd == 2) data = Mcd2Data; + + if (*str == 0) { + sprintf(str, "memcards/card%d.mcd", mcd); + SysPrintf(_("No memory card value was specified - creating a default card %s\n"), str); + } + f = fopen(str, "rb"); + if (f == NULL) { + SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str); + CreateMcd(str); + f = fopen(str, "rb"); + if (f != NULL) { + struct stat buf; + + if (stat(str, &buf) != -1) { + if (buf.st_size == MCD_SIZE + 64) + fseek(f, 64, SEEK_SET); + else if(buf.st_size == MCD_SIZE + 3904) + fseek(f, 3904, SEEK_SET); + } + fread(data, 1, MCD_SIZE, f); + fclose(f); + } + else + SysMessage(_("Memory card %s failed to load!\n"), str); + } + else { + struct stat buf; + SysPrintf(_("Loading memory card %s\n"), str); + if (stat(str, &buf) != -1) { + if (buf.st_size == MCD_SIZE + 64) + fseek(f, 64, SEEK_SET); + else if(buf.st_size == MCD_SIZE + 3904) + fseek(f, 3904, SEEK_SET); + } + fread(data, 1, MCD_SIZE, f); + fclose(f); + } +} + +void LoadMcds(char *mcd1, char *mcd2) { + LoadMcd(1, mcd1); + LoadMcd(2, mcd2); +} + +void SaveMcd(char *mcd, char *data, uint32_t adr, int size) { + FILE *f; + + f = fopen(mcd, "r+b"); + if (f != NULL) { + struct stat buf; + + if (stat(mcd, &buf) != -1) { + if (buf.st_size == MCD_SIZE + 64) + fseek(f, adr + 64, SEEK_SET); + else if (buf.st_size == MCD_SIZE + 3904) + fseek(f, adr + 3904, SEEK_SET); + else + fseek(f, adr, SEEK_SET); + } else + fseek(f, adr, SEEK_SET); + + fwrite(data + adr, 1, size, f); + fclose(f); + return; + } + +#if 0 + // try to create it again if we can't open it + f = fopen(mcd, "wb"); + if (f != NULL) { + fwrite(data, 1, MCD_SIZE, f); + fclose(f); + } +#endif + + ConvertMcd(mcd, data); +} + +void CreateMcd(char *mcd) { + FILE *f; + struct stat buf; + int s = MCD_SIZE; + int i = 0, j; + + f = fopen(mcd, "wb"); + if (f == NULL) + return; + + if (stat(mcd, &buf) != -1) { + if ((buf.st_size == MCD_SIZE + 3904) || strstr(mcd, ".gme")) { + s = s + 3904; + fputc('1', f); + s--; + fputc('2', f); + s--; + fputc('3', f); + s--; + fputc('-', f); + s--; + fputc('4', f); + s--; + fputc('5', f); + s--; + fputc('6', f); + s--; + fputc('-', f); + s--; + fputc('S', f); + s--; + fputc('T', f); + s--; + fputc('D', f); + s--; + for (i = 0; i < 7; i++) { + fputc(0, f); + s--; + } + fputc(1, f); + s--; + fputc(0, f); + s--; + fputc(1, f); + s--; + fputc('M', f); + s--; + fputc('Q', f); + s--; + for (i = 0; i < 14; i++) { + fputc(0xa0, f); + s--; + } + fputc(0, f); + s--; + fputc(0xff, f); + while (s-- > (MCD_SIZE + 1)) + fputc(0, f); + } else if ((buf.st_size == MCD_SIZE + 64) || strstr(mcd, ".mem") || strstr(mcd, ".vgs")) { + s = s + 64; + fputc('V', f); + s--; + fputc('g', f); + s--; + fputc('s', f); + s--; + fputc('M', f); + s--; + for (i = 0; i < 3; i++) { + fputc(1, f); + s--; + fputc(0, f); + s--; + fputc(0, f); + s--; + fputc(0, f); + s--; + } + fputc(0, f); + s--; + fputc(2, f); + while (s-- > (MCD_SIZE + 1)) + fputc(0, f); + } + } + fputc('M', f); + s--; + fputc('C', f); + s--; + while (s-- > (MCD_SIZE - 127)) + fputc(0, f); + fputc(0xe, f); + s--; + + for (i = 0; i < 15; i++) { // 15 blocks + fputc(0xa0, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0xff, f); + s--; + fputc(0xff, f); + s--; + for (j = 0; j < 117; j++) { + fputc(0x00, f); + s--; + } + fputc(0xa0, f); + s--; + } + + for (i = 0; i < 20; i++) { + fputc(0xff, f); + s--; + fputc(0xff, f); + s--; + fputc(0xff, f); + s--; + fputc(0xff, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0x00, f); + s--; + fputc(0xff, f); + s--; + fputc(0xff, f); + s--; + for (j = 0; j < 118; j++) { + fputc(0x00, f); + s--; + } + } + + while ((s--) >= 0) + fputc(0, f); + + fclose(f); +} + +void ConvertMcd(char *mcd, char *data) { + FILE *f; + int i = 0; + int s = MCD_SIZE; + + if (strstr(mcd, ".gme")) { + f = fopen(mcd, "wb"); + if (f != NULL) { + fwrite(data - 3904, 1, MCD_SIZE + 3904, f); + fclose(f); + } + f = fopen(mcd, "r+"); + s = s + 3904; + fputc('1', f); s--; + fputc('2', f); s--; + fputc('3', f); s--; + fputc('-', f); s--; + fputc('4', f); s--; + fputc('5', f); s--; + fputc('6', f); s--; + fputc('-', f); s--; + fputc('S', f); s--; + fputc('T', f); s--; + fputc('D', f); s--; + for (i = 0; i < 7; i++) { + fputc(0, f); s--; + } + fputc(1, f); s--; + fputc(0, f); s--; + fputc(1, f); s--; + fputc('M', f); s--; + fputc('Q', f); s--; + for(i=0;i<14;i++) { + fputc(0xa0, f); s--; + } + fputc(0, f); s--; + fputc(0xff, f); + while (s-- > (MCD_SIZE+1)) fputc(0, f); + fclose(f); + } else if(strstr(mcd, ".mem") || strstr(mcd,".vgs")) { + f = fopen(mcd, "wb"); + if (f != NULL) { + fwrite(data-64, 1, MCD_SIZE+64, f); + fclose(f); + } + f = fopen(mcd, "r+"); + s = s + 64; + fputc('V', f); s--; + fputc('g', f); s--; + fputc('s', f); s--; + fputc('M', f); s--; + for(i=0;i<3;i++) { + fputc(1, f); s--; + fputc(0, f); s--; + fputc(0, f); s--; + fputc(0, f); s--; + } + fputc(0, f); s--; + fputc(2, f); + while (s-- > (MCD_SIZE+1)) fputc(0, f); + fclose(f); + } else { + f = fopen(mcd, "wb"); + if (f != NULL) { + fwrite(data, 1, MCD_SIZE, f); + fclose(f); + } + } +} + +void GetMcdBlockInfo(int mcd, int block, McdBlock *Info) { + unsigned char *data = NULL, *ptr, *str, *sstr; + unsigned short clut[16]; + unsigned short c; + int i, x; + + memset(Info, 0, sizeof(McdBlock)); + + if (mcd == 1) data = Mcd1Data; + if (mcd == 2) data = Mcd2Data; + + ptr = data + block * 8192 + 2; + + Info->IconCount = *ptr & 0x3; + + ptr += 2; + + x = 0; + + str = Info->Title; + sstr = Info->sTitle; + + for (i = 0; i < 48; i++) { + c = *(ptr) << 8; + c |= *(ptr + 1); + if (!c) break; + + // Convert ASCII characters to half-width + if (c >= 0x8281 && c <= 0x829A) + c = (c - 0x8281) + 'a'; + else if (c >= 0x824F && c <= 0x827A) + c = (c - 0x824F) + '0'; + else if (c == 0x8140) c = ' '; + else if (c == 0x8143) c = ','; + else if (c == 0x8144) c = '.'; + else if (c == 0x8146) c = ':'; + else if (c == 0x8147) c = ';'; + else if (c == 0x8148) c = '?'; + else if (c == 0x8149) c = '!'; + else if (c == 0x815E) c = '/'; + else if (c == 0x8168) c = '"'; + else if (c == 0x8169) c = '('; + else if (c == 0x816A) c = ')'; + else if (c == 0x816D) c = '['; + else if (c == 0x816E) c = ']'; + else if (c == 0x817C) c = '-'; + else { + str[i] = ' '; + sstr[x++] = *ptr++; sstr[x++] = *ptr++; + continue; + } + + str[i] = sstr[x++] = c; + ptr += 2; + } + + trim(str); + trim(sstr); + + ptr = data + block * 8192 + 0x60; // icon palette data + + for (i = 0; i < 16; i++) { + clut[i] = *((unsigned short *)ptr); + ptr += 2; + } + + for (i = 0; i < Info->IconCount; i++) { + short *icon = &Info->Icon[i * 16 * 16]; + + ptr = data + block * 8192 + 128 + 128 * i; // icon data + + for (x = 0; x < 16 * 16; x++) { + icon[x++] = clut[*ptr & 0xf]; + icon[x] = clut[*ptr >> 4]; + ptr++; + } + } + + ptr = data + block * 128; + + Info->Flags = *ptr; + + ptr += 0xa; + strncpy(Info->ID, ptr, 12); + ptr += 12; + strncpy(Info->Name, ptr, 16); +} + +int sioFreeze(gzFile f, int Mode) { + gzfreeze(buf, sizeof(buf)); + gzfreeze(&StatReg, sizeof(StatReg)); + gzfreeze(&ModeReg, sizeof(ModeReg)); + gzfreeze(&CtrlReg, sizeof(CtrlReg)); + gzfreeze(&BaudReg, sizeof(BaudReg)); + gzfreeze(&bufcount, sizeof(bufcount)); + gzfreeze(&parp, sizeof(parp)); + gzfreeze(&mcdst, sizeof(mcdst)); + gzfreeze(&rdwr, sizeof(rdwr)); + gzfreeze(&adrH, sizeof(adrH)); + gzfreeze(&adrL, sizeof(adrL)); + gzfreeze(&padst, sizeof(padst)); + + return 0; +} + + +void LoadDongle( char *str ) +{ + FILE *f; + + f = fopen(str, "r+b"); + if (f != NULL) { + fread( DongleData, 1, DONGLE_SIZE, f ); + fclose( f ); + } + else { + u32 *ptr, lcv; + + ptr = (unsigned int *) DongleData; + + // create temp data + ptr[0] = (u32) 0x02015447; + ptr[1] = (u32) 7; + ptr[2] = (u32) 1; + ptr[3] = (u32) 0; + + for( lcv=4; lcv<0x6c / 4; lcv++ ) + { + ptr[ lcv ] = 0; + } + + ptr[ lcv ] = (u32) 0x02000100; + lcv++; + + while( lcv < 0x1000/4 ) + { + ptr[ lcv ] = (u32) 0xffffffff; + lcv++; + } + } +} + +void SaveDongle( char *str ) +{ + FILE *f; + + f = fopen(str, "wb"); + if (f != NULL) { + fwrite( DongleData, 1, DONGLE_SIZE, f ); + fclose( f ); + } +} diff --git a/libpcsxcore/socket.c b/libpcsxcore/socket.c index 450aefd9..f0b19853 100644..100755 --- a/libpcsxcore/socket.c +++ b/libpcsxcore/socket.c @@ -1,254 +1,254 @@ -/* Pcsx - Pc Psx Emulator
- * Copyright (C) 1999-2003 Pcsx 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, see <http://www.gnu.org/licenses>.
- */
-
-#ifdef _WIN32
-#include <winsock2.h>
-#endif
-
-#include "psxcommon.h"
-#include "socket.h"
-
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <fcntl.h>
-#endif
-
-static int server_socket = 0;
-static int client_socket = 0;
-
-static char tbuf[513];
-static int ptr = 0;
-
-#define PORT_NUMBER 12345
-
-int StartServer() {
- struct in_addr localhostaddr;
- struct sockaddr_in localsocketaddr;
-
-#ifdef _WIN32
- WSADATA wsaData;
-
- if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
- return -1;
-#endif
-
- server_socket = socket(AF_INET, SOCK_STREAM, 0);
-
-#ifdef _WIN32
- if (server_socket == INVALID_SOCKET)
- return -1;
-#else
- if (server_socket == -1)
- return -1;
-#endif
-
- SetsNonblock();
-
- memset((void *)&localhostaddr, 0, sizeof(localhostaddr));
- memset(&localsocketaddr, 0, sizeof(struct sockaddr_in));
-
-#ifdef _WIN32
- localhostaddr.S_un.S_addr = htonl(INADDR_ANY);
-#else
- localhostaddr.s_addr = htonl(INADDR_ANY);
-#endif
- localsocketaddr.sin_family = AF_INET;
- localsocketaddr.sin_addr = localhostaddr;
- localsocketaddr.sin_port = htons(PORT_NUMBER);
-
- if (bind(server_socket, (struct sockaddr *) &localsocketaddr, sizeof(localsocketaddr)) < 0)
- return -1;
-
- if (listen(server_socket, 1) != 0)
- return -1;
-
- return 0;
-}
-
-void StopServer() {
-#ifdef _WIN32
- shutdown(server_socket, SD_BOTH);
- closesocket(server_socket);
- WSACleanup();
-#else
- shutdown(server_socket, SHUT_RDWR);
- close(server_socket);
-#endif
-}
-
-void GetClient() {
- int new_socket;
- char hello[256];
-
- new_socket = accept(server_socket, 0, 0);
-
-#ifdef _WIN32
- if (new_socket == INVALID_SOCKET)
- return;
-#else
- if (new_socket == -1)
- return;
-#endif
- if (client_socket)
- CloseClient();
- client_socket = new_socket;
-
-#ifndef _WIN32
- {
- int flags;
- flags = fcntl(client_socket, F_GETFL, 0);
- fcntl(client_socket, F_SETFL, flags | O_NONBLOCK);
- }
-#endif
-
- sprintf(hello, "000 PCSXR Version %s - Debug console\r\n", PACKAGE_VERSION);
- WriteSocket(hello, strlen(hello));
- ptr = 0;
-}
-
-void CloseClient() {
- if (client_socket) {
-#ifdef _WIN32
- shutdown(client_socket, SD_BOTH);
- closesocket(client_socket);
-#else
- shutdown(client_socket, SHUT_RDWR);
- close(client_socket);
-#endif
- client_socket = 0;
- }
-}
-
-int HasClient() {
- return client_socket ? 1 : 0;
-}
-
-int ReadSocket(char * buffer, int len) {
- int r;
- char * endl;
-
- if (!client_socket)
- return -1;
-
- r = recv(client_socket, tbuf + ptr, 512 - ptr, 0);
-
- if (r == 0) {
- client_socket = 0;
- if (!ptr)
- return 0;
- }
-#ifdef _WIN32
- if (r == SOCKET_ERROR)
-#else
- if (r == -1)
-#endif
- {
- if (ptr == 0)
- return -1;
- r = 0;
- }
- ptr += r;
- tbuf[ptr] = 0;
-
- endl = strstr(tbuf, "\r\n");
-
- if (endl) {
- r = endl - tbuf;
- strncpy(buffer, tbuf, r);
-
- r += 2;
- memmove(tbuf, tbuf + r, 512 - r);
- ptr -= r;
- memset(tbuf + r, 0, 512 - r);
- r -= 2;
-
- } else {
- r = 0;
- }
-
- buffer[r] = 0;
-
- return r;
-}
-
-int RawReadSocket(char * buffer, int len) {
- int r = 0;
- int mlen = len < ptr ? len : ptr;
-
- if (!client_socket)
- return -1;
-
- if (ptr) {
- memcpy(buffer, tbuf, mlen);
- ptr -= mlen;
- memmove(tbuf, tbuf + mlen, 512 - mlen);
- }
-
- if (len - mlen)
- r = recv(client_socket, buffer + mlen, len - mlen, 0);
-
- if (r == 0) {
- client_socket = 0;
- if (!ptr)
- return 0;
- }
-#ifdef _WIN32
- if (r == SOCKET_ERROR)
-#else
- if (r == -1)
-#endif
- {
- if (ptr == 0)
- return -1;
- r = 0;
- }
-
- r += mlen;
-
- return r;
-}
-
-void WriteSocket(char * buffer, int len) {
- if (!client_socket)
- return;
-
- send(client_socket, buffer, len, 0);
-}
-
-void SetsBlock() {
-#ifdef _WIN32
- u_long b = 0;
- ioctlsocket(server_socket, FIONBIO, &b);
-#else
- int flags = fcntl(server_socket, F_GETFL, 0);
- fcntl(server_socket, F_SETFL, flags & ~O_NONBLOCK);
-#endif
-}
-
-void SetsNonblock() {
-#ifdef _WIN32
- u_long b = 1;
- ioctlsocket(server_socket, FIONBIO, &b);
-#else
- int flags = fcntl(server_socket, F_GETFL, 0);
- fcntl(server_socket, F_SETFL, flags | O_NONBLOCK);
-#endif
-}
+/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2003 Pcsx 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, see <http://www.gnu.org/licenses>. + */ + +#ifdef _WIN32 +#include <winsock2.h> +#endif + +#include "psxcommon.h" +#include "socket.h" + +#ifndef _WIN32 +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <unistd.h> +#include <fcntl.h> +#endif + +static int server_socket = 0; +static int client_socket = 0; + +static char tbuf[513]; +static int ptr = 0; + +#define PORT_NUMBER 12345 + +int StartServer() { + struct in_addr localhostaddr; + struct sockaddr_in localsocketaddr; + +#ifdef _WIN32 + WSADATA wsaData; + + if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) + return -1; +#endif + + server_socket = socket(AF_INET, SOCK_STREAM, 0); + +#ifdef _WIN32 + if (server_socket == INVALID_SOCKET) + return -1; +#else + if (server_socket == -1) + return -1; +#endif + + SetsNonblock(); + + memset((void *)&localhostaddr, 0, sizeof(localhostaddr)); + memset(&localsocketaddr, 0, sizeof(struct sockaddr_in)); + +#ifdef _WIN32 + localhostaddr.S_un.S_addr = htonl(INADDR_ANY); +#else + localhostaddr.s_addr = htonl(INADDR_ANY); +#endif + localsocketaddr.sin_family = AF_INET; + localsocketaddr.sin_addr = localhostaddr; + localsocketaddr.sin_port = htons(PORT_NUMBER); + + if (bind(server_socket, (struct sockaddr *) &localsocketaddr, sizeof(localsocketaddr)) < 0) + return -1; + + if (listen(server_socket, 1) != 0) + return -1; + + return 0; +} + +void StopServer() { +#ifdef _WIN32 + shutdown(server_socket, SD_BOTH); + closesocket(server_socket); + WSACleanup(); +#else + shutdown(server_socket, SHUT_RDWR); + close(server_socket); +#endif +} + +void GetClient() { + int new_socket; + char hello[256]; + + new_socket = accept(server_socket, 0, 0); + +#ifdef _WIN32 + if (new_socket == INVALID_SOCKET) + return; +#else + if (new_socket == -1) + return; +#endif + if (client_socket) + CloseClient(); + client_socket = new_socket; + +#ifndef _WIN32 + { + int flags; + flags = fcntl(client_socket, F_GETFL, 0); + fcntl(client_socket, F_SETFL, flags | O_NONBLOCK); + } +#endif + + sprintf(hello, "000 PCSXR Version %s - Debug console\r\n", PACKAGE_VERSION); + WriteSocket(hello, strlen(hello)); + ptr = 0; +} + +void CloseClient() { + if (client_socket) { +#ifdef _WIN32 + shutdown(client_socket, SD_BOTH); + closesocket(client_socket); +#else + shutdown(client_socket, SHUT_RDWR); + close(client_socket); +#endif + client_socket = 0; + } +} + +int HasClient() { + return client_socket ? 1 : 0; +} + +int ReadSocket(char * buffer, int len) { + int r; + char * endl; + + if (!client_socket) + return -1; + + r = recv(client_socket, tbuf + ptr, 512 - ptr, 0); + + if (r == 0) { + client_socket = 0; + if (!ptr) + return 0; + } +#ifdef _WIN32 + if (r == SOCKET_ERROR) +#else + if (r == -1) +#endif + { + if (ptr == 0) + return -1; + r = 0; + } + ptr += r; + tbuf[ptr] = 0; + + endl = strstr(tbuf, "\r\n"); + + if (endl) { + r = endl - tbuf; + strncpy(buffer, tbuf, r); + + r += 2; + memmove(tbuf, tbuf + r, 512 - r); + ptr -= r; + memset(tbuf + r, 0, 512 - r); + r -= 2; + + } else { + r = 0; + } + + buffer[r] = 0; + + return r; +} + +int RawReadSocket(char * buffer, int len) { + int r = 0; + int mlen = len < ptr ? len : ptr; + + if (!client_socket) + return -1; + + if (ptr) { + memcpy(buffer, tbuf, mlen); + ptr -= mlen; + memmove(tbuf, tbuf + mlen, 512 - mlen); + } + + if (len - mlen) + r = recv(client_socket, buffer + mlen, len - mlen, 0); + + if (r == 0) { + client_socket = 0; + if (!ptr) + return 0; + } +#ifdef _WIN32 + if (r == SOCKET_ERROR) +#else + if (r == -1) +#endif + { + if (ptr == 0) + return -1; + r = 0; + } + + r += mlen; + + return r; +} + +void WriteSocket(char * buffer, int len) { + if (!client_socket) + return; + + send(client_socket, buffer, len, 0); +} + +void SetsBlock() { +#ifdef _WIN32 + u_long b = 0; + ioctlsocket(server_socket, FIONBIO, &b); +#else + int flags = fcntl(server_socket, F_GETFL, 0); + fcntl(server_socket, F_SETFL, flags & ~O_NONBLOCK); +#endif +} + +void SetsNonblock() { +#ifdef _WIN32 + u_long b = 1; + ioctlsocket(server_socket, FIONBIO, &b); +#else + int flags = fcntl(server_socket, F_GETFL, 0); + fcntl(server_socket, F_SETFL, flags | O_NONBLOCK); +#endif +} |
