summaryrefslogtreecommitdiff
path: root/libpcsxcore
diff options
context:
space:
mode:
Diffstat (limited to 'libpcsxcore')
-rwxr-xr-x[-rw-r--r--]libpcsxcore/cdriso.c2050
-rwxr-xr-x[-rw-r--r--]libpcsxcore/cdriso.h68
-rwxr-xr-x[-rw-r--r--]libpcsxcore/cdrom.c5014
-rwxr-xr-x[-rw-r--r--]libpcsxcore/cdrom.h242
-rwxr-xr-x[-rw-r--r--]libpcsxcore/debug.c2290
-rwxr-xr-x[-rw-r--r--]libpcsxcore/decode_xa.c734
-rwxr-xr-x[-rw-r--r--]libpcsxcore/disr3000a.c674
-rwxr-xr-x[-rw-r--r--]libpcsxcore/gpu.c372
-rwxr-xr-x[-rw-r--r--]libpcsxcore/gpu.h36
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86/iR3000A.c6030
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86/ix86.c3454
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86_64/iR3000A-64.c6050
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86_64/ix86-64.c6286
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86_64/ix86-64.h3552
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86_64/ix86_cpudetect.c984
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86_64/ix86_mmx.c1302
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ix86_64/ix86_sse.c2920
-rwxr-xr-x[-rw-r--r--]libpcsxcore/mdec.c1356
-rwxr-xr-x[-rw-r--r--]libpcsxcore/misc.c1498
-rwxr-xr-x[-rw-r--r--]libpcsxcore/plugins.c1678
-rwxr-xr-x[-rw-r--r--]libpcsxcore/plugins.h848
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ppc/pR3000A.c7086
-rwxr-xr-x[-rw-r--r--]libpcsxcore/ppf.c792
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psemu_plugin_defs.h570
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxbios.c5676
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxbios.h102
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxcommon.h384
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxcounters.c972
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxinterpreter.c2222
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxmem.c748
-rwxr-xr-x[-rw-r--r--]libpcsxcore/psxmem.h288
-rwxr-xr-x[-rw-r--r--]libpcsxcore/r3000a.c534
-rwxr-xr-x[-rw-r--r--]libpcsxcore/r3000a.h678
-rwxr-xr-x[-rw-r--r--]libpcsxcore/sio.c2656
-rwxr-xr-x[-rw-r--r--]libpcsxcore/socket.c508
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", &reg, &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", &reg, &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", &reg, &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", &reg, &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", &reg, &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", &reg, &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", &reg, &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", &reg, &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(&section_address, 4, 1, tmpFile);
- fread(&section_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(&section, 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(&section_address, 4, 1, tmpFile);
+ fread(&section_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(&section, 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
+}